@strkfarm/sdk 2.0.0-dev.26 → 2.0.0-dev.28
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 +79130 -49354
- package/dist/index.browser.mjs +18039 -11431
- package/dist/index.d.ts +2869 -898
- package/dist/index.js +19036 -12207
- package/dist/index.mjs +18942 -12158
- 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/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 +167 -2
- package/src/modules/ExtendedWrapperSDk/types.ts +26 -4
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +110 -67
- 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 +46 -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 +6 -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 +177 -268
- 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 +155 -336
- package/src/strategies/universal-adapters/index.ts +9 -8
- 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 +110 -75
- package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +762 -844
- 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 +396 -204
- package/src/strategies/universal-strategy.tsx +1426 -1178
- package/src/strategies/vesu-extended-strategy/services/executionService.ts +2251 -0
- package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +2941 -0
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +12 -1
- package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +52 -0
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +3 -1
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +158 -124
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +377 -1781
- package/src/strategies/vesu-rebalance.tsx +255 -152
- package/src/utils/health-factor-math.ts +4 -1
- package/src/utils/index.ts +2 -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,6 +3,7 @@ import {
|
|
|
3
3
|
DepositParams,
|
|
4
4
|
WithdrawParams,
|
|
5
5
|
BaseAdapterConfig,
|
|
6
|
+
SwapPriceInfo,
|
|
6
7
|
} from "./baseAdapter";
|
|
7
8
|
import { toBigInt } from "./adapter-utils";
|
|
8
9
|
import { Protocols } from "@/interfaces";
|
|
@@ -19,9 +20,12 @@ import { Quote } from "@avnu/avnu-sdk";
|
|
|
19
20
|
import { hash, uint256 } from "starknet";
|
|
20
21
|
import { AvnuWrapper } from "@/modules/avnu";
|
|
21
22
|
import axios from "axios";
|
|
22
|
-
import {SIMPLE_SANITIZER } from "./adapter-utils";
|
|
23
|
+
import { SIMPLE_SANITIZER } from "./adapter-utils";
|
|
23
24
|
import { returnFormattedAmount } from "../vesu-extended-strategy/utils/helper";
|
|
24
|
-
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";
|
|
25
29
|
export interface AvnuAdapterConfig extends BaseAdapterConfig {
|
|
26
30
|
baseUrl: string;
|
|
27
31
|
avnuContract: ContractAddr; //0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f
|
|
@@ -33,23 +37,163 @@ export interface AvnuAdapterConfig extends BaseAdapterConfig {
|
|
|
33
37
|
export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
34
38
|
readonly config: AvnuAdapterConfig;
|
|
35
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
|
+
}
|
|
36
164
|
|
|
37
165
|
constructor(config: AvnuAdapterConfig) {
|
|
38
166
|
super(config, AvnuAdapter.name, Protocols.AVNU);
|
|
39
167
|
this.config = config as AvnuAdapterConfig;
|
|
40
168
|
this.avnuWrapper = new AvnuWrapper();
|
|
169
|
+
assert(this.config.supportedPositions.length === 2, "AvnuAdapter must have 2 supported positions");
|
|
41
170
|
}
|
|
42
171
|
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
43
172
|
protected async getAPY(
|
|
44
|
-
supportedPosition: SupportedPosition
|
|
173
|
+
supportedPosition: SupportedPosition,
|
|
45
174
|
): Promise<PositionAPY> {
|
|
46
175
|
return Promise.resolve({ apy: 0, type: APYType.BASE });
|
|
47
176
|
}
|
|
48
177
|
|
|
49
178
|
protected async getPosition(
|
|
50
|
-
supportedPosition: SupportedPosition
|
|
51
|
-
): Promise<PositionAmount> {
|
|
52
|
-
|
|
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
|
+
}
|
|
53
197
|
}
|
|
54
198
|
|
|
55
199
|
async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
|
|
@@ -82,31 +226,11 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
82
226
|
sanitizer: ContractAddr;
|
|
83
227
|
id: string;
|
|
84
228
|
}[] {
|
|
85
|
-
|
|
86
|
-
this.config.
|
|
229
|
+
return this.buildSwapLeafConfigs(
|
|
230
|
+
this.config.supportedPositions[0].asset,
|
|
231
|
+
this.config.supportedPositions[1].asset,
|
|
232
|
+
this._depositSwapProofReadableId(),
|
|
87
233
|
);
|
|
88
|
-
return [
|
|
89
|
-
{
|
|
90
|
-
target: this.config.supportedPositions[0].asset.address,
|
|
91
|
-
method: "approve",
|
|
92
|
-
packedArguments: [
|
|
93
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
94
|
-
],
|
|
95
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
96
|
-
id: `approve_${this.config.supportedPositions[0].asset.symbol}`,
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
target: AVNU_EXCHANGE,
|
|
100
|
-
method: "multi_route_swap",
|
|
101
|
-
packedArguments: [
|
|
102
|
-
this.config.supportedPositions[0].asset.address.toBigInt(), //usdc
|
|
103
|
-
this.config.supportedPositions[1].asset.address.toBigInt(), //wbtc
|
|
104
|
-
vaultAllocator.toBigInt(),
|
|
105
|
-
],
|
|
106
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
107
|
-
id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`,
|
|
108
|
-
},
|
|
109
|
-
];
|
|
110
234
|
}
|
|
111
235
|
|
|
112
236
|
protected _getWithdrawLeaf(): {
|
|
@@ -116,33 +240,13 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
116
240
|
sanitizer: ContractAddr;
|
|
117
241
|
id: string;
|
|
118
242
|
}[] {
|
|
119
|
-
const vaultAllocator = ContractAddr.from(
|
|
120
|
-
this.config.vaultAllocator.address
|
|
121
|
-
);
|
|
122
243
|
const toToken = this.config.supportedPositions[0].asset;
|
|
123
244
|
const fromToken = this.config.supportedPositions[1].asset;
|
|
124
|
-
return
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
130
|
-
],
|
|
131
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
132
|
-
id: `approve_${fromToken.symbol}`,
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
target: AVNU_EXCHANGE,
|
|
136
|
-
method: "multi_route_swap",
|
|
137
|
-
packedArguments: [
|
|
138
|
-
fromToken.address.toBigInt(), //wbtc
|
|
139
|
-
toToken.address.toBigInt(), //usdc
|
|
140
|
-
vaultAllocator.toBigInt(),
|
|
141
|
-
],
|
|
142
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
143
|
-
id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`,
|
|
144
|
-
},
|
|
145
|
-
];
|
|
245
|
+
return this.buildSwapLeafConfigs(
|
|
246
|
+
fromToken,
|
|
247
|
+
toToken,
|
|
248
|
+
this._withdrawSwapProofReadableId(),
|
|
249
|
+
);
|
|
146
250
|
}
|
|
147
251
|
|
|
148
252
|
protected _getLegacySwapLeaf(): {
|
|
@@ -159,54 +263,13 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
159
263
|
try {
|
|
160
264
|
const fromToken = this.config.supportedPositions[0].asset; //usdc
|
|
161
265
|
const toToken = this.config.supportedPositions[1].asset; //wbtc
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
toToken.address.toString(),
|
|
168
|
-
params.amount.toNumber(),
|
|
169
|
-
vaultAllocator.address.toString(),
|
|
170
|
-
toToken.decimals,
|
|
171
|
-
true
|
|
172
|
-
)
|
|
173
|
-
//console.log(`${AvnuAdapter.name}::getDepositCall quote: ${JSON.stringify(quote)}`);
|
|
174
|
-
if (!quote) {
|
|
175
|
-
logger.error("error getting quote from avnu");
|
|
176
|
-
return [];
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
180
|
-
quote,
|
|
181
|
-
vaultAllocator.address
|
|
266
|
+
const calls = await this.buildSwapCalls(
|
|
267
|
+
params,
|
|
268
|
+
fromToken,
|
|
269
|
+
toToken,
|
|
270
|
+
true,
|
|
182
271
|
);
|
|
183
|
-
|
|
184
|
-
logger.info(`${AvnuAdapter.name}::getQuotesAvnu finalAmountOfWbtcOut : ${dataObject.avnuFees} ${parseInt(dataObject.buyAmount.toString(), 16)} ${parseInt(dataObject.sellAmount.toString(), 16)} ${parseInt(dataObject.sellAmount.toString(), 16)}`);
|
|
185
|
-
const swapCallData = getCalldata[0];
|
|
186
|
-
// const approveCallData = getCalldata[0];
|
|
187
|
-
const amount = uint256.bnToUint256(quote.sellAmountInUsd*10**7)
|
|
188
|
-
return [
|
|
189
|
-
{
|
|
190
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
191
|
-
call: {
|
|
192
|
-
contractAddress: fromToken.address,
|
|
193
|
-
selector: hash.getSelectorFromName("approve"),
|
|
194
|
-
calldata:[
|
|
195
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
196
|
-
toBigInt(amount.low.toString()), // amount low
|
|
197
|
-
toBigInt(amount.high.toString()), // amount high
|
|
198
|
-
] ,
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
203
|
-
call: {
|
|
204
|
-
contractAddress: AVNU_EXCHANGE,
|
|
205
|
-
selector: hash.getSelectorFromName("multi_route_swap"),
|
|
206
|
-
calldata: swapCallData,
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
];
|
|
272
|
+
return calls;
|
|
210
273
|
} catch (error) {
|
|
211
274
|
logger.error(`Error getting Avnu quote: ${error}`);
|
|
212
275
|
return [];
|
|
@@ -218,49 +281,13 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
218
281
|
try {
|
|
219
282
|
const toToken = this.config.supportedPositions[0].asset;
|
|
220
283
|
const fromToken = this.config.supportedPositions[1].asset;
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
toToken.address.toString(),
|
|
227
|
-
params.amount.toNumber(),
|
|
228
|
-
vaultAllocator.address.toString(),
|
|
229
|
-
fromToken.decimals,
|
|
230
|
-
false
|
|
231
|
-
);
|
|
232
|
-
if (!quote) {
|
|
233
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
234
|
-
return [];
|
|
235
|
-
}
|
|
236
|
-
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
237
|
-
quote,
|
|
238
|
-
vaultAllocator.address
|
|
284
|
+
const calls = await this.buildSwapCalls(
|
|
285
|
+
params,
|
|
286
|
+
fromToken,
|
|
287
|
+
toToken,
|
|
288
|
+
false,
|
|
239
289
|
);
|
|
240
|
-
|
|
241
|
-
const amount = uint256.bnToUint256(params.amount.toWei())
|
|
242
|
-
return [
|
|
243
|
-
{
|
|
244
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
245
|
-
call: {
|
|
246
|
-
contractAddress:fromToken.address,
|
|
247
|
-
selector: hash.getSelectorFromName("approve"),
|
|
248
|
-
calldata: [
|
|
249
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
250
|
-
toBigInt(amount.low.toString()), // amount low
|
|
251
|
-
toBigInt(amount.high.toString()), // amount high
|
|
252
|
-
],
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
257
|
-
call: {
|
|
258
|
-
contractAddress: AVNU_EXCHANGE,
|
|
259
|
-
selector: hash.getSelectorFromName("multi_route_swap"),
|
|
260
|
-
calldata: swapCallData,
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
];
|
|
290
|
+
return calls;
|
|
264
291
|
} catch (error) {
|
|
265
292
|
logger.error(`Error getting Avnu quote: ${error}`);
|
|
266
293
|
return [];
|
|
@@ -268,7 +295,10 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
268
295
|
}
|
|
269
296
|
|
|
270
297
|
async getSwapCallData(quote: Quote): Promise<bigint[][]> {
|
|
271
|
-
return await this.avnuWrapper.getSwapCallData(
|
|
298
|
+
return await this.avnuWrapper.getSwapCallData(
|
|
299
|
+
quote,
|
|
300
|
+
this.config.vaultAllocator.address,
|
|
301
|
+
);
|
|
272
302
|
}
|
|
273
303
|
|
|
274
304
|
async getHealthFactor(): Promise<number> {
|
|
@@ -277,7 +307,7 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
277
307
|
|
|
278
308
|
async fetchQuoteWithRetry(
|
|
279
309
|
params: Record<string, any>,
|
|
280
|
-
retries: number = 5
|
|
310
|
+
retries: number = 5,
|
|
281
311
|
): Promise<any> {
|
|
282
312
|
for (let attempt = 0; attempt < retries; attempt++) {
|
|
283
313
|
try {
|
|
@@ -296,125 +326,4 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
296
326
|
}
|
|
297
327
|
throw new Error("Failed to fetch quote after retries");
|
|
298
328
|
}
|
|
299
|
-
|
|
300
|
-
async getQuotesAvnu (
|
|
301
|
-
from_token_address: string,
|
|
302
|
-
to_token_address: string,
|
|
303
|
-
amount: number, //amount in btc units
|
|
304
|
-
takerAddress: string,
|
|
305
|
-
toTokenDecimals: number,
|
|
306
|
-
usdcToBtc: boolean,
|
|
307
|
-
maxIterations: number = 5,
|
|
308
|
-
tolerance: number = 5000
|
|
309
|
-
): Promise<Quote | null>{
|
|
310
|
-
try {
|
|
311
|
-
const fromToken = this.config.supportedPositions[0].asset; //usdc
|
|
312
|
-
const toToken = this.config.supportedPositions[1].asset; //wbtc
|
|
313
|
-
if(!usdcToBtc) {
|
|
314
|
-
const sellAmount = returnFormattedAmount(amount, toTokenDecimals);
|
|
315
|
-
const params: Record<string, any> = {
|
|
316
|
-
sellTokenAddress: from_token_address,
|
|
317
|
-
buyTokenAddress: to_token_address,
|
|
318
|
-
takerAddress,
|
|
319
|
-
sellAmount:sellAmount,
|
|
320
|
-
};
|
|
321
|
-
const finalQuote = await this.fetchQuoteWithRetry(params);
|
|
322
|
-
if (!finalQuote.data.length) {
|
|
323
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
324
|
-
return null;
|
|
325
|
-
}
|
|
326
|
-
const dataObject: Quote = finalQuote.data[0];
|
|
327
|
-
return dataObject;
|
|
328
|
-
}
|
|
329
|
-
const btcPrice = await this.getPriceOfToken(toToken.address.toString());
|
|
330
|
-
if (!btcPrice) {
|
|
331
|
-
logger.error(`error getting btc price: ${btcPrice}`);
|
|
332
|
-
return null;
|
|
333
|
-
}
|
|
334
|
-
const estimatedUsdcAmount = Math.floor(amount * btcPrice);
|
|
335
|
-
logger.info(`${AvnuAdapter.name}::getQuotesAvnu estimatedUsdcAmount: ${estimatedUsdcAmount}`);
|
|
336
|
-
const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
|
|
337
|
-
logger.info(`${AvnuAdapter.name}::getQuotesAvnu targetBtcBig: ${targetBtcBig}`);
|
|
338
|
-
let low = BigInt(
|
|
339
|
-
Math.floor(
|
|
340
|
-
(estimatedUsdcAmount * 10 ** fromToken.decimals) * 0.9
|
|
341
|
-
)
|
|
342
|
-
);
|
|
343
|
-
let high = BigInt(
|
|
344
|
-
Math.floor(
|
|
345
|
-
(estimatedUsdcAmount * 10 ** fromToken.decimals) * 1.1
|
|
346
|
-
)
|
|
347
|
-
);
|
|
348
|
-
let mid = 0n;
|
|
349
|
-
for (let i = 0; i < maxIterations; i++) {
|
|
350
|
-
mid = (low + high) / 2n;
|
|
351
|
-
const sellAmount = returnFormattedAmount(Number(mid), 0);
|
|
352
|
-
const quote = await this.fetchQuoteWithRetry({
|
|
353
|
-
sellTokenAddress: from_token_address,
|
|
354
|
-
buyTokenAddress: to_token_address,
|
|
355
|
-
takerAddress,
|
|
356
|
-
sellAmount,
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
const gotBtc = BigInt(quote.data[0].buyAmount);
|
|
360
|
-
if (gotBtc === targetBtcBig) return quote.data[0];
|
|
361
|
-
|
|
362
|
-
if (gotBtc > targetBtcBig) {
|
|
363
|
-
high = mid;
|
|
364
|
-
} else {
|
|
365
|
-
low = mid;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
if (
|
|
369
|
-
gotBtc >= targetBtcBig &&
|
|
370
|
-
gotBtc <= targetBtcBig + BigInt(tolerance)
|
|
371
|
-
) {
|
|
372
|
-
return quote.data[0];
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
let sellAmount = returnFormattedAmount(
|
|
376
|
-
Number(mid),
|
|
377
|
-
0
|
|
378
|
-
);
|
|
379
|
-
const params: Record<string, any> = {
|
|
380
|
-
sellTokenAddress: from_token_address,
|
|
381
|
-
buyTokenAddress: to_token_address,
|
|
382
|
-
takerAddress,
|
|
383
|
-
sellAmount: sellAmount,
|
|
384
|
-
};
|
|
385
|
-
const finalQuote = await this.fetchQuoteWithRetry(params);
|
|
386
|
-
if (!finalQuote.data.length) {
|
|
387
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
388
|
-
return null;
|
|
389
|
-
}
|
|
390
|
-
const dataObject: Quote = finalQuote.data[0];
|
|
391
|
-
const wbtcAmountOut = parseInt(dataObject.buyAmount.toString(), 16);
|
|
392
|
-
logger.info(`${AvnuAdapter.name}::getQuotesAvnu finalAmountOfWbtcOut : ${wbtcAmountOut} ${dataObject.buyAmount} ${dataObject.sellAmount.toString()} ${dataObject.sellAmount.toString()}`);
|
|
393
|
-
return dataObject;
|
|
394
|
-
} catch (err) {
|
|
395
|
-
logger.error(`No quotes available for this swap: ${err}`);
|
|
396
|
-
return null;
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
async getPriceOfToken (
|
|
401
|
-
tokenAddress: string,
|
|
402
|
-
retries: number = MAX_RETRIES
|
|
403
|
-
): Promise<number | null> {
|
|
404
|
-
try {
|
|
405
|
-
const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
|
|
406
|
-
const response = await axios.get(url);
|
|
407
|
-
const length = response.data.length;
|
|
408
|
-
return response.data[length - 1].value;
|
|
409
|
-
} catch (err) {
|
|
410
|
-
if (retries > 0) {
|
|
411
|
-
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
412
|
-
return this.getPriceOfToken(tokenAddress, retries - 1);
|
|
413
|
-
} else {
|
|
414
|
-
logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
|
|
415
|
-
return null;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
}
|
|
329
|
+
}
|