@strkfarm/sdk 2.0.0-dev.4 → 2.0.0-dev.41
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 +116250 -90801
- package/dist/index.browser.mjs +13050 -10957
- package/dist/index.d.ts +2232 -1933
- package/dist/index.js +13380 -11084
- package/dist/index.mjs +13280 -11007
- package/package.json +6 -7
- package/src/data/avnu.abi.json +840 -0
- package/src/data/ekubo-price-fethcer.abi.json +265 -0
- package/src/data/redeem-request-nft.abi.json +752 -0
- package/src/data/universal-vault.abi.json +8 -7
- package/src/dataTypes/_bignumber.ts +13 -4
- package/src/dataTypes/bignumber.browser.ts +10 -1
- package/src/dataTypes/bignumber.node.ts +10 -1
- package/src/dataTypes/index.ts +3 -2
- package/src/dataTypes/mynumber.ts +141 -0
- package/src/global.ts +93 -36
- package/src/index.browser.ts +2 -1
- package/src/interfaces/common.tsx +218 -5
- package/src/modules/apollo-client-config.ts +28 -0
- package/src/modules/avnu.ts +21 -12
- 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/index.ts +2 -1
- package/src/modules/pragma.ts +23 -8
- package/src/modules/pricer-avnu-api.ts +114 -0
- package/src/modules/pricer-from-api.ts +156 -15
- package/src/modules/pricer-lst.ts +1 -1
- package/src/modules/pricer.ts +94 -40
- package/src/modules/pricerBase.ts +2 -1
- package/src/node/deployer.ts +36 -1
- package/src/node/pricer-redis.ts +3 -1
- package/src/strategies/base-strategy.ts +168 -16
- package/src/strategies/constants.ts +8 -3
- package/src/strategies/ekubo-cl-vault.tsx +1047 -351
- package/src/strategies/factory.ts +199 -0
- package/src/strategies/index.ts +5 -3
- package/src/strategies/registry.ts +262 -0
- package/src/strategies/sensei.ts +353 -9
- package/src/strategies/svk-strategy.ts +283 -31
- package/src/strategies/token-boosted-xstrk-carry-strategy.tsx +1262 -0
- package/src/strategies/types.ts +4 -0
- package/src/strategies/universal-adapters/adapter-utils.ts +4 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +196 -272
- package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
- package/src/strategies/universal-adapters/common-adapter.ts +206 -203
- package/src/strategies/universal-adapters/index.ts +10 -8
- package/src/strategies/universal-adapters/svk-troves-adapter.ts +511 -0
- package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +120 -82
- package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +525 -0
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +1098 -712
- package/src/strategies/universal-adapters/vesu-position-common.ts +258 -0
- package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
- package/src/strategies/universal-lst-muliplier-strategy.tsx +631 -414
- package/src/strategies/universal-strategy.tsx +1331 -1173
- package/src/strategies/vesu-rebalance.tsx +252 -152
- package/src/strategies/yoloVault.ts +1087 -0
- package/src/utils/cacheClass.ts +11 -2
- package/src/utils/health-factor-math.ts +33 -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/modules/ExtendedWrapperSDk/index.ts +0 -62
- package/src/modules/ExtendedWrapperSDk/types.ts +0 -311
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +0 -395
- package/src/strategies/universal-adapters/extended-adapter.ts +0 -661
- package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +0 -34
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +0 -77
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +0 -49
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +0 -372
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +0 -1140
|
@@ -2,6 +2,8 @@ import { ContractAddr } from "@/dataTypes";
|
|
|
2
2
|
|
|
3
3
|
// Zellic audited
|
|
4
4
|
export const SIMPLE_SANITIZER = ContractAddr.from('0x5a2e3ceb3da368b983a8717898427ab7b6daf04014b70f321e777f9aad940b4');
|
|
5
|
+
// Above SIMPLE_SANITIZER was not exposing the request_redeem method
|
|
6
|
+
export const SVK_SIMPLE_SANITIZER = ContractAddr.from('0x03dcde04343257c3ce14574676cb9c5b2eda16e332c1b8caf5dc4c95ac568d2f')
|
|
5
7
|
export const EXTENDED_SANITIZER = ContractAddr.from('0x65891708362b24dcf4c40c8e218cce6e82d1d6b3a3404c9ab00a48f08e2c110');
|
|
6
8
|
export const AVNU_LEGACY_SANITIZER = ContractAddr.from('0x0656fBE853f116DD53956176a553eDe8fE65632252f8aceB50C1B9B6c8237309');
|
|
7
9
|
// Without flashloan options
|
|
@@ -15,6 +17,7 @@ export const AVNU_EXCHANGE_FOR_LEGACY_USDC = ContractAddr.from('0x7bffc7f6bda62b
|
|
|
15
17
|
export const AVNU_QUOTE_URL = "https://starknet.api.avnu.fi/swap/v3/quotes";
|
|
16
18
|
export const EXTENDED_CONTRACT = ContractAddr.from('0x062da0780fae50d68cecaa5a051606dc21217ba290969b302db4dd99d2e9b470');
|
|
17
19
|
export const VESU_SINGLETON = ContractAddr.from('0x000d8d6dfec4d33bfb6895de9f3852143a17c6f92fd2a21da3d6924d34870160');
|
|
20
|
+
export const TRANSFER_SANITIZER = ContractAddr.from('0x07c94fd8762b37b02c2afeaf37e5d77523a2aedd370ccff6e130b2d5e9e23037');
|
|
18
21
|
export function toBigInt(value: string | number): bigint {
|
|
19
22
|
if (typeof value === 'string') {
|
|
20
23
|
return BigInt(value);
|
|
@@ -23,4 +26,4 @@ export function toBigInt(value: string | number): bigint {
|
|
|
23
26
|
} else {
|
|
24
27
|
throw new Error('Value must be a string or number');
|
|
25
28
|
}
|
|
26
|
-
}
|
|
29
|
+
}
|
|
@@ -3,52 +3,206 @@ 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
|
-
import { MAX_DELAY } from "../vesu-extended-strategy/utils/constants";
|
|
10
10
|
import { SupportedPosition } from "./baseAdapter";
|
|
11
11
|
import { PositionAPY, APYType, PositionAmount } from "./baseAdapter";
|
|
12
12
|
import { Web3Number } from "@/dataTypes";
|
|
13
13
|
import { PositionInfo } from "./baseAdapter";
|
|
14
14
|
import { ManageCall } from "./baseAdapter";
|
|
15
15
|
import { ContractAddr } from "@/dataTypes";
|
|
16
|
-
import { TokenInfo } from "@/interfaces";
|
|
17
16
|
import { AVNU_EXCHANGE } from "./adapter-utils";
|
|
18
|
-
import { MAX_RETRIES } from "../vesu-extended-strategy/utils/constants";
|
|
19
17
|
import { Quote } from "@avnu/avnu-sdk";
|
|
20
18
|
import { hash, uint256 } from "starknet";
|
|
21
19
|
import { AvnuWrapper } from "@/modules/avnu";
|
|
22
20
|
import axios from "axios";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
21
|
+
import { SIMPLE_SANITIZER } from "./adapter-utils";
|
|
22
|
+
import { assert, logger } from "@/utils";
|
|
23
|
+
import { Global } from "@/global";
|
|
24
|
+
import { TokenInfo } from "@/interfaces";
|
|
25
|
+
import { ERC20 } from "@/modules";
|
|
26
|
+
import { MAX_AVNU_RETRY_DELAY } from "../constants";
|
|
27
|
+
|
|
28
|
+
export interface AvnuDepositParams extends DepositParams {
|
|
29
|
+
minAmount?: Web3Number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface AvnuWithdrawParams extends WithdrawParams {
|
|
33
|
+
minAmount?: Web3Number;
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
export interface AvnuAdapterConfig extends BaseAdapterConfig {
|
|
27
37
|
baseUrl: string;
|
|
28
38
|
avnuContract: ContractAddr; //0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f
|
|
29
39
|
slippage: number;
|
|
40
|
+
minimumExtendedPriceDifferenceForSwapOpen: number;
|
|
41
|
+
maximumExtendedPriceDifferenceForSwapClosing: number;
|
|
30
42
|
}
|
|
31
43
|
|
|
32
|
-
export class AvnuAdapter extends BaseAdapter<
|
|
44
|
+
export class AvnuAdapter extends BaseAdapter<AvnuDepositParams, AvnuWithdrawParams> {
|
|
33
45
|
readonly config: AvnuAdapterConfig;
|
|
34
46
|
protected avnuWrapper: AvnuWrapper;
|
|
47
|
+
lastSwapPriceInfo: SwapPriceInfo | null = null;
|
|
48
|
+
|
|
49
|
+
private _depositApproveProofReadableId(): string {
|
|
50
|
+
return `approve_${this.config.supportedPositions[0].asset.symbol}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private _depositSwapProofReadableId(): string {
|
|
54
|
+
return `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private _withdrawApproveProofReadableId(): string {
|
|
58
|
+
return `approve_${this.config.supportedPositions[1].asset.symbol}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private _withdrawSwapProofReadableId(): string {
|
|
62
|
+
const fromToken = this.config.supportedPositions[1].asset;
|
|
63
|
+
return `asbtu_${fromToken.symbol}_${fromToken.symbol}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private buildSwapLeafConfigs(
|
|
67
|
+
fromToken: TokenInfo,
|
|
68
|
+
toToken: TokenInfo,
|
|
69
|
+
swapId: string,
|
|
70
|
+
): {
|
|
71
|
+
target: ContractAddr;
|
|
72
|
+
method: string;
|
|
73
|
+
packedArguments: bigint[];
|
|
74
|
+
sanitizer: ContractAddr;
|
|
75
|
+
id: string;
|
|
76
|
+
}[] {
|
|
77
|
+
const vaultAllocator = ContractAddr.from(this.config.vaultAllocator.address);
|
|
78
|
+
return [
|
|
79
|
+
{
|
|
80
|
+
target: fromToken.address,
|
|
81
|
+
method: "approve",
|
|
82
|
+
packedArguments: [AVNU_EXCHANGE.toBigInt()],
|
|
83
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
84
|
+
id: `approve_${fromToken.symbol}`,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
target: AVNU_EXCHANGE,
|
|
88
|
+
method: "multi_route_swap",
|
|
89
|
+
packedArguments: [
|
|
90
|
+
fromToken.address.toBigInt(),
|
|
91
|
+
toToken.address.toBigInt(),
|
|
92
|
+
vaultAllocator.toBigInt(),
|
|
93
|
+
],
|
|
94
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
95
|
+
id: swapId,
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private async buildSwapCalls(
|
|
101
|
+
params: AvnuDepositParams | AvnuWithdrawParams,
|
|
102
|
+
fromToken: TokenInfo,
|
|
103
|
+
toToken: TokenInfo,
|
|
104
|
+
// NOTE : this is a direction flag that we are swapping in this direction
|
|
105
|
+
usdcToBtc: boolean,
|
|
106
|
+
): Promise<ManageCall[]> {
|
|
107
|
+
const vaultAllocator = ContractAddr.from(this.config.vaultAllocator.address);
|
|
108
|
+
const quote = await this.avnuWrapper.getQuotes(
|
|
109
|
+
fromToken.address.toString(),
|
|
110
|
+
toToken.address.toString(),
|
|
111
|
+
params.amount.toWei(),
|
|
112
|
+
vaultAllocator.address.toString(),
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (!quote) {
|
|
116
|
+
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const fromAmt = Web3Number.fromWei(quote.sellAmount.toString(), fromToken.decimals).toNumber();
|
|
121
|
+
const toAmt = Web3Number.fromWei(quote.buyAmount.toString(), toToken.decimals).toNumber();
|
|
122
|
+
this.lastSwapPriceInfo = {
|
|
123
|
+
source: 'avnu',
|
|
124
|
+
fromTokenSymbol: fromToken.symbol,
|
|
125
|
+
toTokenSymbol: toToken.symbol,
|
|
126
|
+
fromAmount: fromAmt,
|
|
127
|
+
toAmount: toAmt,
|
|
128
|
+
effectivePrice: toAmt !== 0 ? fromAmt / toAmt : 0,
|
|
129
|
+
};
|
|
130
|
+
logger.verbose(
|
|
131
|
+
`${AvnuAdapter.name}::buildSwapCalls stored price info: ` +
|
|
132
|
+
`${fromAmt} ${fromToken.symbol} → ${toAmt} ${toToken.symbol}, ` +
|
|
133
|
+
`effectivePrice=${this.lastSwapPriceInfo.effectivePrice}`,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
137
|
+
quote,
|
|
138
|
+
vaultAllocator.address,
|
|
139
|
+
params.minAmount,
|
|
140
|
+
);
|
|
141
|
+
const swapCallData = getCalldata[0];
|
|
142
|
+
const approveAmount = uint256.bnToUint256(params.amount.toWei());
|
|
143
|
+
|
|
144
|
+
return [
|
|
145
|
+
{
|
|
146
|
+
proofReadableId: usdcToBtc
|
|
147
|
+
? this._depositApproveProofReadableId()
|
|
148
|
+
: this._withdrawApproveProofReadableId(),
|
|
149
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
150
|
+
call: {
|
|
151
|
+
contractAddress: fromToken.address,
|
|
152
|
+
selector: hash.getSelectorFromName("approve"),
|
|
153
|
+
calldata: [
|
|
154
|
+
AVNU_EXCHANGE.toBigInt(),
|
|
155
|
+
toBigInt(approveAmount.low.toString()),
|
|
156
|
+
toBigInt(approveAmount.high.toString()),
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
proofReadableId: usdcToBtc
|
|
162
|
+
? this._depositSwapProofReadableId()
|
|
163
|
+
: this._withdrawSwapProofReadableId(),
|
|
164
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
165
|
+
call: {
|
|
166
|
+
contractAddress: AVNU_EXCHANGE,
|
|
167
|
+
selector: hash.getSelectorFromName("multi_route_swap"),
|
|
168
|
+
calldata: swapCallData,
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
];
|
|
172
|
+
}
|
|
35
173
|
|
|
36
174
|
constructor(config: AvnuAdapterConfig) {
|
|
37
175
|
super(config, AvnuAdapter.name, Protocols.AVNU);
|
|
38
176
|
this.config = config as AvnuAdapterConfig;
|
|
39
177
|
this.avnuWrapper = new AvnuWrapper();
|
|
178
|
+
assert(this.config.supportedPositions.length === 2, "AvnuAdapter must have 2 supported positions");
|
|
40
179
|
}
|
|
41
180
|
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
42
181
|
protected async getAPY(
|
|
43
|
-
supportedPosition: SupportedPosition
|
|
182
|
+
supportedPosition: SupportedPosition,
|
|
44
183
|
): Promise<PositionAPY> {
|
|
45
184
|
return Promise.resolve({ apy: 0, type: APYType.BASE });
|
|
46
185
|
}
|
|
47
186
|
|
|
48
187
|
protected async getPosition(
|
|
49
|
-
supportedPosition: SupportedPosition
|
|
50
|
-
): Promise<PositionAmount> {
|
|
51
|
-
|
|
188
|
+
supportedPosition: SupportedPosition,
|
|
189
|
+
): Promise<PositionAmount | null> {
|
|
190
|
+
const toToken = this.config.supportedPositions[1].asset;
|
|
191
|
+
if (supportedPosition.asset.symbol != toToken.symbol) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
// only measure balance of toToken, bcz from token usually gets trakced in unused balance or a previous avnu adapter
|
|
196
|
+
const balance = await new ERC20(this.config.networkConfig).balanceOf(
|
|
197
|
+
supportedPosition.asset.address,
|
|
198
|
+
this.config.vaultAllocator.address,
|
|
199
|
+
supportedPosition.asset.decimals,
|
|
200
|
+
);
|
|
201
|
+
return { amount: balance, remarks: `Swapped Unused balance (VA)` };
|
|
202
|
+
} catch (_e) {
|
|
203
|
+
logger.error(`${AvnuAdapter.name}::getPosition: failed for ${toToken.symbol}`);
|
|
204
|
+
throw new Error(`${AvnuAdapter.name}: failed to get balance for ${toToken.symbol}`);
|
|
205
|
+
}
|
|
52
206
|
}
|
|
53
207
|
|
|
54
208
|
async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
|
|
@@ -81,31 +235,11 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
81
235
|
sanitizer: ContractAddr;
|
|
82
236
|
id: string;
|
|
83
237
|
}[] {
|
|
84
|
-
|
|
85
|
-
this.config.
|
|
238
|
+
return this.buildSwapLeafConfigs(
|
|
239
|
+
this.config.supportedPositions[0].asset,
|
|
240
|
+
this.config.supportedPositions[1].asset,
|
|
241
|
+
this._depositSwapProofReadableId(),
|
|
86
242
|
);
|
|
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
243
|
}
|
|
110
244
|
|
|
111
245
|
protected _getWithdrawLeaf(): {
|
|
@@ -115,33 +249,13 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
115
249
|
sanitizer: ContractAddr;
|
|
116
250
|
id: string;
|
|
117
251
|
}[] {
|
|
118
|
-
const vaultAllocator = ContractAddr.from(
|
|
119
|
-
this.config.vaultAllocator.address
|
|
120
|
-
);
|
|
121
252
|
const toToken = this.config.supportedPositions[0].asset;
|
|
122
253
|
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
|
-
];
|
|
254
|
+
return this.buildSwapLeafConfigs(
|
|
255
|
+
fromToken,
|
|
256
|
+
toToken,
|
|
257
|
+
this._withdrawSwapProofReadableId(),
|
|
258
|
+
);
|
|
145
259
|
}
|
|
146
260
|
|
|
147
261
|
protected _getLegacySwapLeaf(): {
|
|
@@ -154,57 +268,17 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
154
268
|
return [];
|
|
155
269
|
}
|
|
156
270
|
|
|
157
|
-
async getDepositCall(params:
|
|
271
|
+
async getDepositCall(params: AvnuDepositParams): Promise<ManageCall[]> {
|
|
158
272
|
try {
|
|
159
273
|
const fromToken = this.config.supportedPositions[0].asset; //usdc
|
|
160
274
|
const toToken = this.config.supportedPositions[1].asset; //wbtc
|
|
161
|
-
const
|
|
162
|
-
|
|
275
|
+
const calls = await this.buildSwapCalls(
|
|
276
|
+
params,
|
|
277
|
+
fromToken,
|
|
278
|
+
toToken,
|
|
279
|
+
true,
|
|
163
280
|
);
|
|
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
|
-
];
|
|
281
|
+
return calls;
|
|
208
282
|
} catch (error) {
|
|
209
283
|
logger.error(`Error getting Avnu quote: ${error}`);
|
|
210
284
|
return [];
|
|
@@ -212,53 +286,17 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
212
286
|
}
|
|
213
287
|
|
|
214
288
|
//Swap wbtc to usdc
|
|
215
|
-
async getWithdrawCall(params:
|
|
289
|
+
async getWithdrawCall(params: AvnuWithdrawParams): Promise<ManageCall[]> {
|
|
216
290
|
try {
|
|
217
291
|
const toToken = this.config.supportedPositions[0].asset;
|
|
218
292
|
const fromToken = this.config.supportedPositions[1].asset;
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
|
293
|
+
const calls = await this.buildSwapCalls(
|
|
294
|
+
params,
|
|
295
|
+
fromToken,
|
|
296
|
+
toToken,
|
|
297
|
+
false,
|
|
237
298
|
);
|
|
238
|
-
|
|
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
|
-
];
|
|
299
|
+
return calls;
|
|
262
300
|
} catch (error) {
|
|
263
301
|
logger.error(`Error getting Avnu quote: ${error}`);
|
|
264
302
|
return [];
|
|
@@ -266,7 +304,10 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
266
304
|
}
|
|
267
305
|
|
|
268
306
|
async getSwapCallData(quote: Quote): Promise<bigint[][]> {
|
|
269
|
-
return await this.avnuWrapper.getSwapCallData(
|
|
307
|
+
return await this.avnuWrapper.getSwapCallData(
|
|
308
|
+
quote,
|
|
309
|
+
this.config.vaultAllocator.address,
|
|
310
|
+
);
|
|
270
311
|
}
|
|
271
312
|
|
|
272
313
|
async getHealthFactor(): Promise<number> {
|
|
@@ -275,7 +316,7 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
275
316
|
|
|
276
317
|
async fetchQuoteWithRetry(
|
|
277
318
|
params: Record<string, any>,
|
|
278
|
-
retries: number = 5
|
|
319
|
+
retries: number = 5,
|
|
279
320
|
): Promise<any> {
|
|
280
321
|
for (let attempt = 0; attempt < retries; attempt++) {
|
|
281
322
|
try {
|
|
@@ -289,126 +330,9 @@ export class AvnuAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
|
|
|
289
330
|
if (attempt === retries - 1) {
|
|
290
331
|
throw err;
|
|
291
332
|
}
|
|
292
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
333
|
+
await new Promise((resolve) => setTimeout(resolve, MAX_AVNU_RETRY_DELAY));
|
|
293
334
|
}
|
|
294
335
|
}
|
|
295
336
|
throw new Error("Failed to fetch quote after retries");
|
|
296
337
|
}
|
|
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
|
-
}
|
|
338
|
+
}
|