@strkfarm/sdk 2.0.0-dev.3 → 2.0.0-dev.31
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 +190 -36
- package/dist/cli.mjs +188 -34
- package/dist/index.browser.global.js +78475 -45620
- package/dist/index.browser.mjs +19580 -9901
- package/dist/index.d.ts +3763 -1424
- package/dist/index.js +20977 -11063
- package/dist/index.mjs +20945 -11087
- package/package.json +1 -1
- package/src/data/avnu.abi.json +840 -0
- package/src/data/ekubo-price-fethcer.abi.json +265 -0
- package/src/dataTypes/_bignumber.ts +13 -4
- package/src/dataTypes/bignumber.browser.ts +6 -1
- package/src/dataTypes/bignumber.node.ts +5 -1
- package/src/dataTypes/index.ts +3 -2
- package/src/dataTypes/mynumber.ts +141 -0
- package/src/global.ts +76 -41
- package/src/index.browser.ts +2 -1
- package/src/interfaces/common.tsx +175 -3
- package/src/modules/ExtendedWrapperSDk/types.ts +28 -5
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +275 -59
- package/src/modules/apollo-client-config.ts +28 -0
- package/src/modules/avnu.ts +4 -4
- package/src/modules/ekubo-pricer.ts +79 -0
- package/src/modules/ekubo-quoter.ts +48 -30
- package/src/modules/erc20.ts +17 -0
- package/src/modules/harvests.ts +43 -29
- package/src/modules/pragma.ts +23 -8
- package/src/modules/pricer-from-api.ts +156 -15
- package/src/modules/pricer-lst.ts +1 -1
- package/src/modules/pricer.ts +40 -4
- package/src/modules/pricerBase.ts +2 -1
- package/src/node/deployer.ts +36 -1
- package/src/node/pricer-redis.ts +2 -1
- package/src/strategies/base-strategy.ts +78 -10
- package/src/strategies/ekubo-cl-vault.tsx +906 -347
- package/src/strategies/factory.ts +159 -0
- package/src/strategies/index.ts +7 -1
- package/src/strategies/registry.ts +239 -0
- package/src/strategies/sensei.ts +335 -7
- package/src/strategies/svk-strategy.ts +97 -27
- package/src/strategies/types.ts +4 -0
- package/src/strategies/universal-adapters/adapter-utils.ts +2 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +180 -265
- package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
- package/src/strategies/universal-adapters/common-adapter.ts +206 -203
- package/src/strategies/universal-adapters/extended-adapter.ts +490 -316
- package/src/strategies/universal-adapters/index.ts +11 -8
- package/src/strategies/universal-adapters/svk-troves-adapter.ts +364 -0
- package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
- package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +200 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +120 -82
- package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +1067 -704
- package/src/strategies/universal-adapters/vesu-position-common.ts +251 -0
- package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
- package/src/strategies/universal-lst-muliplier-strategy.tsx +397 -204
- package/src/strategies/universal-strategy.tsx +1426 -1173
- package/src/strategies/vesu-extended-strategy/services/executionService.ts +2233 -0
- package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +4087 -0
- package/src/strategies/vesu-extended-strategy/services/ltv-imbalance-rebalance-math.ts +783 -0
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +38 -16
- package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +88 -0
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +5 -6
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +259 -103
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +688 -817
- package/src/strategies/vesu-rebalance.tsx +255 -152
- package/src/utils/cacheClass.ts +11 -2
- package/src/utils/health-factor-math.ts +4 -1
- package/src/utils/index.ts +3 -1
- package/src/utils/logger.browser.ts +22 -4
- package/src/utils/logger.node.ts +259 -24
- package/src/utils/starknet-call-parser.ts +1036 -0
- package/src/utils/strategy-utils.ts +61 -0
- package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
|
@@ -3,8 +3,9 @@ import {
|
|
|
3
3
|
DepositParams,
|
|
4
4
|
WithdrawParams,
|
|
5
5
|
BaseAdapterConfig,
|
|
6
|
+
SwapPriceInfo,
|
|
6
7
|
} from "./baseAdapter";
|
|
7
|
-
import {
|
|
8
|
+
import { toBigInt } from "./adapter-utils";
|
|
8
9
|
import { Protocols } from "@/interfaces";
|
|
9
10
|
import { MAX_DELAY } from "../vesu-extended-strategy/utils/constants";
|
|
10
11
|
import { SupportedPosition } from "./baseAdapter";
|
|
@@ -13,42 +14,186 @@ import { Web3Number } from "@/dataTypes";
|
|
|
13
14
|
import { PositionInfo } from "./baseAdapter";
|
|
14
15
|
import { ManageCall } from "./baseAdapter";
|
|
15
16
|
import { ContractAddr } from "@/dataTypes";
|
|
16
|
-
import { TokenInfo } from "@/interfaces";
|
|
17
17
|
import { AVNU_EXCHANGE } from "./adapter-utils";
|
|
18
18
|
import { MAX_RETRIES } from "../vesu-extended-strategy/utils/constants";
|
|
19
19
|
import { Quote } from "@avnu/avnu-sdk";
|
|
20
20
|
import { hash, uint256 } from "starknet";
|
|
21
21
|
import { AvnuWrapper } from "@/modules/avnu";
|
|
22
22
|
import axios from "axios";
|
|
23
|
-
import {
|
|
23
|
+
import { SIMPLE_SANITIZER } from "./adapter-utils";
|
|
24
24
|
import { returnFormattedAmount } from "../vesu-extended-strategy/utils/helper";
|
|
25
|
-
import { logger } from "@/utils";
|
|
25
|
+
import { assert, logger } from "@/utils";
|
|
26
|
+
import { Global } from "@/global";
|
|
27
|
+
import { TokenInfo } from "@/interfaces";
|
|
28
|
+
import { ERC20 } from "@/modules";
|
|
26
29
|
export interface AvnuAdapterConfig extends BaseAdapterConfig {
|
|
27
30
|
baseUrl: string;
|
|
28
31
|
avnuContract: ContractAddr; //0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f
|
|
29
32
|
slippage: number;
|
|
33
|
+
minimumExtendedPriceDifferenceForSwapOpen: number;
|
|
34
|
+
maximumExtendedPriceDifferenceForSwapClosing: number;
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
33
38
|
readonly config: AvnuAdapterConfig;
|
|
34
39
|
protected avnuWrapper: AvnuWrapper;
|
|
40
|
+
lastSwapPriceInfo: SwapPriceInfo | null = null;
|
|
41
|
+
|
|
42
|
+
private _depositApproveProofReadableId(): string {
|
|
43
|
+
return `approve_${this.config.supportedPositions[0].asset.symbol}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private _depositSwapProofReadableId(): string {
|
|
47
|
+
return `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private _withdrawApproveProofReadableId(): string {
|
|
51
|
+
return `approve_${this.config.supportedPositions[1].asset.symbol}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private _withdrawSwapProofReadableId(): string {
|
|
55
|
+
const fromToken = this.config.supportedPositions[1].asset;
|
|
56
|
+
return `asbtu_${fromToken.symbol}_${fromToken.symbol}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private buildSwapLeafConfigs(
|
|
60
|
+
fromToken: TokenInfo,
|
|
61
|
+
toToken: TokenInfo,
|
|
62
|
+
swapId: string,
|
|
63
|
+
): {
|
|
64
|
+
target: ContractAddr;
|
|
65
|
+
method: string;
|
|
66
|
+
packedArguments: bigint[];
|
|
67
|
+
sanitizer: ContractAddr;
|
|
68
|
+
id: string;
|
|
69
|
+
}[] {
|
|
70
|
+
const vaultAllocator = ContractAddr.from(this.config.vaultAllocator.address);
|
|
71
|
+
return [
|
|
72
|
+
{
|
|
73
|
+
target: fromToken.address,
|
|
74
|
+
method: "approve",
|
|
75
|
+
packedArguments: [AVNU_EXCHANGE.toBigInt()],
|
|
76
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
77
|
+
id: `approve_${fromToken.symbol}`,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
target: AVNU_EXCHANGE,
|
|
81
|
+
method: "multi_route_swap",
|
|
82
|
+
packedArguments: [
|
|
83
|
+
fromToken.address.toBigInt(),
|
|
84
|
+
toToken.address.toBigInt(),
|
|
85
|
+
vaultAllocator.toBigInt(),
|
|
86
|
+
],
|
|
87
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
88
|
+
id: swapId,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private async buildSwapCalls(
|
|
94
|
+
params: DepositParams | WithdrawParams,
|
|
95
|
+
fromToken: TokenInfo,
|
|
96
|
+
toToken: TokenInfo,
|
|
97
|
+
usdcToBtc: boolean,
|
|
98
|
+
): Promise<ManageCall[]> {
|
|
99
|
+
const vaultAllocator = ContractAddr.from(this.config.vaultAllocator.address);
|
|
100
|
+
const quote = await this.avnuWrapper.getQuotes(
|
|
101
|
+
fromToken.address.toString(),
|
|
102
|
+
toToken.address.toString(),
|
|
103
|
+
params.amount.toWei(),
|
|
104
|
+
vaultAllocator.address.toString(),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
if (!quote) {
|
|
108
|
+
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const fromAmt = Web3Number.fromWei(quote.sellAmount.toString(), fromToken.decimals).toNumber();
|
|
113
|
+
const toAmt = Web3Number.fromWei(quote.buyAmount.toString(), toToken.decimals).toNumber();
|
|
114
|
+
this.lastSwapPriceInfo = {
|
|
115
|
+
source: 'avnu',
|
|
116
|
+
fromTokenSymbol: fromToken.symbol,
|
|
117
|
+
toTokenSymbol: toToken.symbol,
|
|
118
|
+
fromAmount: fromAmt,
|
|
119
|
+
toAmount: toAmt,
|
|
120
|
+
effectivePrice: toAmt !== 0 ? fromAmt / toAmt : 0,
|
|
121
|
+
};
|
|
122
|
+
logger.verbose(
|
|
123
|
+
`${AvnuAdapter.name}::buildSwapCalls stored price info: ` +
|
|
124
|
+
`${fromAmt} ${fromToken.symbol} → ${toAmt} ${toToken.symbol}, ` +
|
|
125
|
+
`effectivePrice=${this.lastSwapPriceInfo.effectivePrice}`,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
129
|
+
quote,
|
|
130
|
+
vaultAllocator.address,
|
|
131
|
+
);
|
|
132
|
+
const swapCallData = getCalldata[0];
|
|
133
|
+
const approveAmount = uint256.bnToUint256(params.amount.toWei());
|
|
134
|
+
|
|
135
|
+
return [
|
|
136
|
+
{
|
|
137
|
+
proofReadableId: usdcToBtc
|
|
138
|
+
? this._depositApproveProofReadableId()
|
|
139
|
+
: this._withdrawApproveProofReadableId(),
|
|
140
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
141
|
+
call: {
|
|
142
|
+
contractAddress: fromToken.address,
|
|
143
|
+
selector: hash.getSelectorFromName("approve"),
|
|
144
|
+
calldata: [
|
|
145
|
+
AVNU_EXCHANGE.toBigInt(),
|
|
146
|
+
toBigInt(approveAmount.low.toString()),
|
|
147
|
+
toBigInt(approveAmount.high.toString()),
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
proofReadableId: usdcToBtc
|
|
153
|
+
? this._depositSwapProofReadableId()
|
|
154
|
+
: this._withdrawSwapProofReadableId(),
|
|
155
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
156
|
+
call: {
|
|
157
|
+
contractAddress: AVNU_EXCHANGE,
|
|
158
|
+
selector: hash.getSelectorFromName("multi_route_swap"),
|
|
159
|
+
calldata: swapCallData,
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
];
|
|
163
|
+
}
|
|
35
164
|
|
|
36
165
|
constructor(config: AvnuAdapterConfig) {
|
|
37
166
|
super(config, AvnuAdapter.name, Protocols.AVNU);
|
|
38
167
|
this.config = config as AvnuAdapterConfig;
|
|
39
168
|
this.avnuWrapper = new AvnuWrapper();
|
|
169
|
+
assert(this.config.supportedPositions.length === 2, "AvnuAdapter must have 2 supported positions");
|
|
40
170
|
}
|
|
41
171
|
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
42
172
|
protected async getAPY(
|
|
43
|
-
supportedPosition: SupportedPosition
|
|
173
|
+
supportedPosition: SupportedPosition,
|
|
44
174
|
): Promise<PositionAPY> {
|
|
45
175
|
return Promise.resolve({ apy: 0, type: APYType.BASE });
|
|
46
176
|
}
|
|
47
177
|
|
|
48
178
|
protected async getPosition(
|
|
49
|
-
supportedPosition: SupportedPosition
|
|
50
|
-
): Promise<PositionAmount> {
|
|
51
|
-
|
|
179
|
+
supportedPosition: SupportedPosition,
|
|
180
|
+
): Promise<PositionAmount | null> {
|
|
181
|
+
const toToken = this.config.supportedPositions[1].asset;
|
|
182
|
+
if (supportedPosition.asset.symbol != toToken.symbol) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
// only measure balance of toToken, bcz from token usually gets trakced in unused balance or a previous avnu adapter
|
|
187
|
+
const balance = await new ERC20(this.config.networkConfig).balanceOf(
|
|
188
|
+
supportedPosition.asset.address,
|
|
189
|
+
this.config.vaultAllocator.address,
|
|
190
|
+
supportedPosition.asset.decimals,
|
|
191
|
+
);
|
|
192
|
+
return { amount: balance, remarks: `Swapped Unused balance (VA)` };
|
|
193
|
+
} catch (_e) {
|
|
194
|
+
logger.error(`${AvnuAdapter.name}::getPosition: failed for ${toToken.symbol}`);
|
|
195
|
+
throw new Error(`${AvnuAdapter.name}: failed to get balance for ${toToken.symbol}`);
|
|
196
|
+
}
|
|
52
197
|
}
|
|
53
198
|
|
|
54
199
|
async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
|
|
@@ -81,31 +226,11 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
81
226
|
sanitizer: ContractAddr;
|
|
82
227
|
id: string;
|
|
83
228
|
}[] {
|
|
84
|
-
|
|
85
|
-
this.config.
|
|
229
|
+
return this.buildSwapLeafConfigs(
|
|
230
|
+
this.config.supportedPositions[0].asset,
|
|
231
|
+
this.config.supportedPositions[1].asset,
|
|
232
|
+
this._depositSwapProofReadableId(),
|
|
86
233
|
);
|
|
87
|
-
return [
|
|
88
|
-
{
|
|
89
|
-
target: this.config.supportedPositions[0].asset.address,
|
|
90
|
-
method: "approve",
|
|
91
|
-
packedArguments: [
|
|
92
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
93
|
-
],
|
|
94
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
95
|
-
id: `approve_${this.config.supportedPositions[0].asset.symbol}`,
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
target: AVNU_EXCHANGE,
|
|
99
|
-
method: "multi_route_swap",
|
|
100
|
-
packedArguments: [
|
|
101
|
-
this.config.supportedPositions[0].asset.address.toBigInt(), //usdc
|
|
102
|
-
this.config.supportedPositions[1].asset.address.toBigInt(), //wbtc
|
|
103
|
-
vaultAllocator.toBigInt(),
|
|
104
|
-
],
|
|
105
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
106
|
-
id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`,
|
|
107
|
-
},
|
|
108
|
-
];
|
|
109
234
|
}
|
|
110
235
|
|
|
111
236
|
protected _getWithdrawLeaf(): {
|
|
@@ -115,33 +240,13 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
115
240
|
sanitizer: ContractAddr;
|
|
116
241
|
id: string;
|
|
117
242
|
}[] {
|
|
118
|
-
const vaultAllocator = ContractAddr.from(
|
|
119
|
-
this.config.vaultAllocator.address
|
|
120
|
-
);
|
|
121
243
|
const toToken = this.config.supportedPositions[0].asset;
|
|
122
244
|
const fromToken = this.config.supportedPositions[1].asset;
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
129
|
-
],
|
|
130
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
131
|
-
id: `approve_${fromToken.symbol}`,
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
target: AVNU_EXCHANGE,
|
|
135
|
-
method: "multi_route_swap",
|
|
136
|
-
packedArguments: [
|
|
137
|
-
fromToken.address.toBigInt(), //wbtc
|
|
138
|
-
toToken.address.toBigInt(), //usdc
|
|
139
|
-
vaultAllocator.toBigInt(),
|
|
140
|
-
],
|
|
141
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
142
|
-
id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`,
|
|
143
|
-
},
|
|
144
|
-
];
|
|
245
|
+
return this.buildSwapLeafConfigs(
|
|
246
|
+
fromToken,
|
|
247
|
+
toToken,
|
|
248
|
+
this._withdrawSwapProofReadableId(),
|
|
249
|
+
);
|
|
145
250
|
}
|
|
146
251
|
|
|
147
252
|
protected _getLegacySwapLeaf(): {
|
|
@@ -158,53 +263,13 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
158
263
|
try {
|
|
159
264
|
const fromToken = this.config.supportedPositions[0].asset; //usdc
|
|
160
265
|
const toToken = this.config.supportedPositions[1].asset; //wbtc
|
|
161
|
-
const
|
|
162
|
-
|
|
266
|
+
const calls = await this.buildSwapCalls(
|
|
267
|
+
params,
|
|
268
|
+
fromToken,
|
|
269
|
+
toToken,
|
|
270
|
+
true,
|
|
163
271
|
);
|
|
164
|
-
|
|
165
|
-
fromToken.address.toString(),
|
|
166
|
-
toToken.address.toString(),
|
|
167
|
-
params.amount.toNumber(),
|
|
168
|
-
vaultAllocator.address.toString(),
|
|
169
|
-
toToken.decimals,
|
|
170
|
-
true
|
|
171
|
-
)
|
|
172
|
-
//console.log(`${AvnuAdapter.name}::getDepositCall quote: ${JSON.stringify(quote)}`);
|
|
173
|
-
if (!quote) {
|
|
174
|
-
logger.error("error getting quote from avnu");
|
|
175
|
-
return [];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
179
|
-
quote,
|
|
180
|
-
vaultAllocator.address
|
|
181
|
-
);
|
|
182
|
-
const swapCallData = getCalldata[0];
|
|
183
|
-
|
|
184
|
-
// const approveCallData = getCalldata[0];
|
|
185
|
-
const amount = uint256.bnToUint256(quote.sellAmountInUsd*10**7)
|
|
186
|
-
return [
|
|
187
|
-
{
|
|
188
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
189
|
-
call: {
|
|
190
|
-
contractAddress: fromToken.address,
|
|
191
|
-
selector: hash.getSelectorFromName("approve"),
|
|
192
|
-
calldata:[
|
|
193
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
194
|
-
toBigInt(amount.low.toString()), // amount low
|
|
195
|
-
toBigInt(amount.high.toString()), // amount high
|
|
196
|
-
] ,
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
201
|
-
call: {
|
|
202
|
-
contractAddress: AVNU_EXCHANGE,
|
|
203
|
-
selector: hash.getSelectorFromName("multi_route_swap"),
|
|
204
|
-
calldata: swapCallData,
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
];
|
|
272
|
+
return calls;
|
|
208
273
|
} catch (error) {
|
|
209
274
|
logger.error(`Error getting Avnu quote: ${error}`);
|
|
210
275
|
return [];
|
|
@@ -216,49 +281,13 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
216
281
|
try {
|
|
217
282
|
const toToken = this.config.supportedPositions[0].asset;
|
|
218
283
|
const fromToken = this.config.supportedPositions[1].asset;
|
|
219
|
-
const
|
|
220
|
-
|
|
284
|
+
const calls = await this.buildSwapCalls(
|
|
285
|
+
params,
|
|
286
|
+
fromToken,
|
|
287
|
+
toToken,
|
|
288
|
+
false,
|
|
221
289
|
);
|
|
222
|
-
|
|
223
|
-
fromToken.address.toString(),
|
|
224
|
-
toToken.address.toString(),
|
|
225
|
-
params.amount.toNumber(),
|
|
226
|
-
vaultAllocator.address.toString(),
|
|
227
|
-
fromToken.decimals,
|
|
228
|
-
false
|
|
229
|
-
);
|
|
230
|
-
if (!quote) {
|
|
231
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
232
|
-
return [];
|
|
233
|
-
}
|
|
234
|
-
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
235
|
-
quote,
|
|
236
|
-
vaultAllocator.address
|
|
237
|
-
);
|
|
238
|
-
const swapCallData = getCalldata[0];
|
|
239
|
-
const amount = uint256.bnToUint256(params.amount.toWei())
|
|
240
|
-
return [
|
|
241
|
-
{
|
|
242
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
243
|
-
call: {
|
|
244
|
-
contractAddress:fromToken.address,
|
|
245
|
-
selector: hash.getSelectorFromName("approve"),
|
|
246
|
-
calldata: [
|
|
247
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
248
|
-
toBigInt(amount.low.toString()), // amount low
|
|
249
|
-
toBigInt(amount.high.toString()), // amount high
|
|
250
|
-
],
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
255
|
-
call: {
|
|
256
|
-
contractAddress: AVNU_EXCHANGE,
|
|
257
|
-
selector: hash.getSelectorFromName("multi_route_swap"),
|
|
258
|
-
calldata: swapCallData,
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
];
|
|
290
|
+
return calls;
|
|
262
291
|
} catch (error) {
|
|
263
292
|
logger.error(`Error getting Avnu quote: ${error}`);
|
|
264
293
|
return [];
|
|
@@ -266,7 +295,10 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
266
295
|
}
|
|
267
296
|
|
|
268
297
|
async getSwapCallData(quote: Quote): Promise<bigint[][]> {
|
|
269
|
-
return await this.avnuWrapper.getSwapCallData(
|
|
298
|
+
return await this.avnuWrapper.getSwapCallData(
|
|
299
|
+
quote,
|
|
300
|
+
this.config.vaultAllocator.address,
|
|
301
|
+
);
|
|
270
302
|
}
|
|
271
303
|
|
|
272
304
|
async getHealthFactor(): Promise<number> {
|
|
@@ -275,7 +307,7 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
275
307
|
|
|
276
308
|
async fetchQuoteWithRetry(
|
|
277
309
|
params: Record<string, any>,
|
|
278
|
-
retries: number = 5
|
|
310
|
+
retries: number = 5,
|
|
279
311
|
): Promise<any> {
|
|
280
312
|
for (let attempt = 0; attempt < retries; attempt++) {
|
|
281
313
|
try {
|
|
@@ -294,121 +326,4 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
294
326
|
}
|
|
295
327
|
throw new Error("Failed to fetch quote after retries");
|
|
296
328
|
}
|
|
297
|
-
|
|
298
|
-
async getQuotesAvnu (
|
|
299
|
-
from_token_address: string,
|
|
300
|
-
to_token_address: string,
|
|
301
|
-
amount: number, //amount in btc units
|
|
302
|
-
takerAddress: string,
|
|
303
|
-
toTokenDecimals: number,
|
|
304
|
-
usdcToBtc: boolean,
|
|
305
|
-
maxIterations: number = 5,
|
|
306
|
-
tolerance: number = 1000
|
|
307
|
-
): Promise<Quote | null>{
|
|
308
|
-
try {
|
|
309
|
-
const fromToken = this.config.supportedPositions[0].asset;
|
|
310
|
-
const toToken = this.config.supportedPositions[1].asset;
|
|
311
|
-
if(!usdcToBtc) {
|
|
312
|
-
const sellAmount = returnFormattedAmount(amount, toTokenDecimals);
|
|
313
|
-
const params: Record<string, any> = {
|
|
314
|
-
sellTokenAddress: from_token_address,
|
|
315
|
-
buyTokenAddress: to_token_address,
|
|
316
|
-
takerAddress,
|
|
317
|
-
sellAmount:sellAmount,
|
|
318
|
-
};
|
|
319
|
-
const finalQuote = await this.fetchQuoteWithRetry(params);
|
|
320
|
-
if (!finalQuote.data.length) {
|
|
321
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
322
|
-
return null;
|
|
323
|
-
}
|
|
324
|
-
const dataObject: Quote = finalQuote.data[0];
|
|
325
|
-
return dataObject;
|
|
326
|
-
}
|
|
327
|
-
const btcPrice = await this.getPriceOfToken(toToken.address.toString());
|
|
328
|
-
if (!btcPrice) {
|
|
329
|
-
logger.error(`error getting btc price: ${btcPrice}`);
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
const estimatedUsdcAmount = Math.floor(amount * btcPrice);
|
|
333
|
-
const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
|
|
334
|
-
let low = BigInt(
|
|
335
|
-
Math.floor(
|
|
336
|
-
(estimatedUsdcAmount * 10 ** fromToken.decimals) * 0.9
|
|
337
|
-
)
|
|
338
|
-
);
|
|
339
|
-
let high = BigInt(
|
|
340
|
-
Math.floor(
|
|
341
|
-
(estimatedUsdcAmount * 10 ** fromToken.decimals) * 1.1
|
|
342
|
-
)
|
|
343
|
-
);
|
|
344
|
-
let mid = 0n;
|
|
345
|
-
for (let i = 0; i < maxIterations; i++) {
|
|
346
|
-
mid = (low + high) / 2n;
|
|
347
|
-
const sellAmount = returnFormattedAmount(Number(mid), 0);
|
|
348
|
-
const quote = await this.fetchQuoteWithRetry({
|
|
349
|
-
sellTokenAddress: from_token_address,
|
|
350
|
-
buyTokenAddress: to_token_address,
|
|
351
|
-
takerAddress,
|
|
352
|
-
sellAmount,
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
const gotBtc = BigInt(quote.data[0].buyAmount);
|
|
356
|
-
if (gotBtc === targetBtcBig) return quote.data[0];
|
|
357
|
-
|
|
358
|
-
if (gotBtc > targetBtcBig) {
|
|
359
|
-
high = mid;
|
|
360
|
-
} else {
|
|
361
|
-
low = mid;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (
|
|
365
|
-
gotBtc >= targetBtcBig &&
|
|
366
|
-
gotBtc <= targetBtcBig + BigInt(tolerance)
|
|
367
|
-
) {
|
|
368
|
-
return quote.data[0];
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
let sellAmount = returnFormattedAmount(
|
|
372
|
-
Number(mid),
|
|
373
|
-
0
|
|
374
|
-
);
|
|
375
|
-
const params: Record<string, any> = {
|
|
376
|
-
sellTokenAddress: from_token_address,
|
|
377
|
-
buyTokenAddress: to_token_address,
|
|
378
|
-
takerAddress,
|
|
379
|
-
sellAmount: sellAmount,
|
|
380
|
-
};
|
|
381
|
-
const finalQuote = await this.fetchQuoteWithRetry(params);
|
|
382
|
-
if (!finalQuote.data.length) {
|
|
383
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
384
|
-
return null;
|
|
385
|
-
}
|
|
386
|
-
const dataObject: Quote = finalQuote.data[0];
|
|
387
|
-
return dataObject;
|
|
388
|
-
} catch (err) {
|
|
389
|
-
logger.error(`No quotes available for this swap: ${err}`);
|
|
390
|
-
return null;
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
|
|
394
|
-
async getPriceOfToken (
|
|
395
|
-
tokenAddress: string,
|
|
396
|
-
retries: number = MAX_RETRIES
|
|
397
|
-
): Promise<number | null> {
|
|
398
|
-
try {
|
|
399
|
-
const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
|
|
400
|
-
const response = await axios.get(url);
|
|
401
|
-
const length = response.data.length;
|
|
402
|
-
return response.data[length - 1].value;
|
|
403
|
-
} catch (err) {
|
|
404
|
-
if (retries > 0) {
|
|
405
|
-
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
406
|
-
return this.getPriceOfToken(tokenAddress, retries - 1);
|
|
407
|
-
} else {
|
|
408
|
-
logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
|
|
409
|
-
return null;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
}
|
|
329
|
+
}
|