@strkfarm/sdk 2.0.0-dev.27 → 2.0.0-dev.29

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.
Files changed (74) hide show
  1. package/dist/cli.js +190 -36
  2. package/dist/cli.mjs +188 -34
  3. package/dist/index.browser.global.js +78495 -47555
  4. package/dist/index.browser.mjs +19327 -11553
  5. package/dist/index.d.ts +3664 -1474
  6. package/dist/index.js +20346 -12343
  7. package/dist/index.mjs +20293 -12340
  8. package/package.json +1 -1
  9. package/src/data/avnu.abi.json +840 -0
  10. package/src/data/ekubo-price-fethcer.abi.json +265 -0
  11. package/src/dataTypes/_bignumber.ts +13 -4
  12. package/src/dataTypes/bignumber.browser.ts +6 -1
  13. package/src/dataTypes/bignumber.node.ts +5 -1
  14. package/src/dataTypes/index.ts +3 -2
  15. package/src/dataTypes/mynumber.ts +141 -0
  16. package/src/global.ts +76 -41
  17. package/src/index.browser.ts +2 -1
  18. package/src/interfaces/common.tsx +175 -3
  19. package/src/modules/ExtendedWrapperSDk/types.ts +26 -4
  20. package/src/modules/ExtendedWrapperSDk/wrapper.ts +110 -67
  21. package/src/modules/apollo-client-config.ts +28 -0
  22. package/src/modules/avnu.ts +4 -4
  23. package/src/modules/ekubo-pricer.ts +79 -0
  24. package/src/modules/ekubo-quoter.ts +46 -30
  25. package/src/modules/erc20.ts +17 -0
  26. package/src/modules/harvests.ts +43 -29
  27. package/src/modules/pragma.ts +23 -8
  28. package/src/modules/pricer-from-api.ts +156 -15
  29. package/src/modules/pricer-lst.ts +1 -1
  30. package/src/modules/pricer.ts +40 -4
  31. package/src/modules/pricerBase.ts +2 -1
  32. package/src/node/deployer.ts +36 -1
  33. package/src/node/pricer-redis.ts +2 -1
  34. package/src/strategies/base-strategy.ts +78 -10
  35. package/src/strategies/ekubo-cl-vault.tsx +906 -347
  36. package/src/strategies/factory.ts +159 -0
  37. package/src/strategies/index.ts +6 -1
  38. package/src/strategies/registry.ts +239 -0
  39. package/src/strategies/sensei.ts +335 -7
  40. package/src/strategies/svk-strategy.ts +97 -27
  41. package/src/strategies/types.ts +4 -0
  42. package/src/strategies/universal-adapters/adapter-utils.ts +2 -1
  43. package/src/strategies/universal-adapters/avnu-adapter.ts +177 -268
  44. package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
  45. package/src/strategies/universal-adapters/common-adapter.ts +206 -203
  46. package/src/strategies/universal-adapters/extended-adapter.ts +155 -336
  47. package/src/strategies/universal-adapters/index.ts +11 -9
  48. package/src/strategies/universal-adapters/svk-troves-adapter.ts +364 -0
  49. package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
  50. package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +200 -0
  51. package/src/strategies/universal-adapters/vesu-adapter.ts +110 -75
  52. package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
  53. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +817 -845
  54. package/src/strategies/universal-adapters/vesu-position-common.ts +251 -0
  55. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
  56. package/src/strategies/universal-lst-muliplier-strategy.tsx +396 -204
  57. package/src/strategies/universal-strategy.tsx +1426 -1178
  58. package/src/strategies/vesu-extended-strategy/services/executionService.ts +2232 -0
  59. package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +3956 -0
  60. package/src/strategies/vesu-extended-strategy/services/ltv-imbalance-rebalance-math.ts +730 -0
  61. package/src/strategies/vesu-extended-strategy/services/operationService.ts +12 -0
  62. package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +52 -0
  63. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
  64. package/src/strategies/vesu-extended-strategy/utils/constants.ts +2 -0
  65. package/src/strategies/vesu-extended-strategy/utils/helper.ts +158 -124
  66. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +333 -1800
  67. package/src/strategies/vesu-rebalance.tsx +255 -152
  68. package/src/utils/health-factor-math.ts +4 -1
  69. package/src/utils/index.ts +3 -1
  70. package/src/utils/logger.browser.ts +22 -4
  71. package/src/utils/logger.node.ts +259 -24
  72. package/src/utils/starknet-call-parser.ts +1036 -0
  73. package/src/utils/strategy-utils.ts +61 -0
  74. package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
@@ -1,9 +1,11 @@
1
- export * from "./baseAdapter";
2
- export * from "./common-adapter";
3
- export * from "./vesu-adapter";
4
- export * from "./vesu-supply-only-adapter";
5
- export * from "./vesu-multiply-adapter";
6
- export * from "./extended-adapter";
7
- export * from "./adapter-utils";
8
- export * from "./unused-balance-adapter";
9
- export * from "./avnu-adapter";
1
+ export * from "./baseAdapter";
2
+ export * from "./common-adapter";
3
+ export * from "./vesu-adapter";
4
+ export * from "./vesu-supply-only-adapter";
5
+ export * from "./vesu-multiply-adapter";
6
+ export * from "./vesu-modify-position-adapter";
7
+ export * from "./extended-adapter";
8
+ export * from "./adapter-utils";
9
+ export * from "./token-transfer-adapter";
10
+ export * from "./avnu-adapter";
11
+ export * from "./svk-troves-adapter";
@@ -0,0 +1,364 @@
1
+ import { ContractAddr, Web3Number } from "@/dataTypes";
2
+ import { Protocols } from "@/interfaces";
3
+ import {
4
+ BaseAdapter,
5
+ BaseAdapterConfig,
6
+ SupportedPosition,
7
+ PositionInfo,
8
+ PositionAPY,
9
+ APYType,
10
+ ManageCall,
11
+ AdapterLeafType,
12
+ GenerateCallFn,
13
+ DepositParams,
14
+ WithdrawParams,
15
+ PositionAmount,
16
+ } from "./baseAdapter";
17
+ import { SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
18
+ import { hash, uint256, Contract } from "starknet";
19
+ import { logger } from "@/utils";
20
+ // Troves SVK universal vault ABI: ERC-4626 + SVK views (e.g. due_assets_from_owner).
21
+ import universalVaultAbi from "@/data/universal-vault.abi.json";
22
+
23
+ /** Public Troves strategies feed (APY + metadata). Override in config for tests. */
24
+ export const DEFAULT_TROVES_STRATEGIES_API = "https://app.troves.fi/api/strategies";
25
+
26
+ export interface SvkTrovesAdapterConfig extends BaseAdapterConfig {
27
+ /**
28
+ * On-chain Troves / SVK strategy vault: ERC-4626-style `deposit` / `withdraw` on the underlying asset,
29
+ * plus `due_assets_from_owner` for redemption NFT value still owed to an owner.
30
+ */
31
+ strategyVault: ContractAddr;
32
+ /**
33
+ * Troves API `strategies[].id` string (e.g. `hyper_xstrk`). Used to resolve APY from the public JSON feed.
34
+ */
35
+ trovesStrategyId: string;
36
+ /**
37
+ * Address whose vault **share** balance and **pending** redemption assets are measured.
38
+ * Defaults to `vaultAllocator` when omitted (typical STRKFarm vault wiring).
39
+ */
40
+ positionOwner?: ContractAddr;
41
+ /** Optional APY endpoint (defaults to {@link DEFAULT_TROVES_STRATEGIES_API}). */
42
+ trovesStrategiesApiUrl?: string;
43
+ }
44
+
45
+ type TrovesStrategiesApiPayload = {
46
+ strategies?: Array<{
47
+ id: string;
48
+ apy?: number | string;
49
+ }>;
50
+ };
51
+
52
+ function parseTrovesApyField(raw: unknown): number {
53
+ if (typeof raw === "number" && Number.isFinite(raw)) {
54
+ return raw;
55
+ }
56
+ if (typeof raw === "string") {
57
+ const n = Number.parseFloat(raw);
58
+ if (Number.isFinite(n)) {
59
+ return n;
60
+ }
61
+ }
62
+ return 0;
63
+ }
64
+
65
+ /**
66
+ * Universal adapter for **Starknet Vault Kit (SVK)** style Troves strategies:
67
+ * approve underlying → `deposit(assets, receiver)`, and `withdraw(assets, receiver, owner)` on the strategy vault.
68
+ *
69
+ * **Position sizing** (underlying asset, same decimals as `baseToken`):
70
+ * - Liquid: `convert_to_assets(balance_of(positionOwner))` on the strategy vault (vault shares).
71
+ * - Pending redemptions: `due_assets_from_owner(positionOwner)` on the same vault (NFT / queue claims not yet settled).
72
+ *
73
+ * **APY**: Fetched from Troves public API by `trovesStrategyId` (numeric `apy` field; non-numeric marketing values fall back to `0`).
74
+ */
75
+ export class SvkTrovesAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
76
+ readonly config: SvkTrovesAdapterConfig;
77
+
78
+ constructor(config: SvkTrovesAdapterConfig) {
79
+ super(config, SvkTrovesAdapter.name, Protocols.TROVES);
80
+ this.config = config;
81
+ }
82
+
83
+ /** Owner used for share balance + `due_assets_from_owner`. */
84
+ private _positionOwner(): ContractAddr {
85
+ return this.config.positionOwner ?? this.config.vaultAllocator;
86
+ }
87
+
88
+ /**
89
+ * Proof readable IDs must stay ≤ 31 chars (Cairo short string). We derive a short ASCII suffix from
90
+ * `strategyVault` address so multiple SVK adapters in one tree stay distinct.
91
+ */
92
+ private _proofSuffix(): string {
93
+ return this.config.strategyVault.address.replace(/^0x/, "").slice(-6);
94
+ }
95
+
96
+ private _depositApproveProofReadableId(): string {
97
+ return `appr_dep_svk_${this._proofSuffix()}`;
98
+ }
99
+
100
+ private _depositCallProofReadableId(): string {
101
+ return `dep_svk_${this._proofSuffix()}`;
102
+ }
103
+
104
+ private _withdrawCallProofReadableId(): string {
105
+ return `wtdrw_svk_${this._proofSuffix()}`;
106
+ }
107
+
108
+ protected async getAPY(supportedPosition: SupportedPosition): Promise<PositionAPY> {
109
+ const CACHE_KEY = `svk_apy_${this.config.trovesStrategyId}`;
110
+ const cached = this.getCache<PositionAPY>(CACHE_KEY);
111
+ if (cached) {
112
+ return cached;
113
+ }
114
+
115
+ const url = this.config.trovesStrategiesApiUrl ?? DEFAULT_TROVES_STRATEGIES_API;
116
+
117
+ try {
118
+ const res = await fetch(url);
119
+ if (!res.ok) {
120
+ logger.warn(`${SvkTrovesAdapter.name}::getAPY: HTTP ${res.status} from ${url}`);
121
+ const fallback = { apy: 0, type: APYType.BASE };
122
+ this.setCache(CACHE_KEY, fallback, 300_000);
123
+ return fallback;
124
+ }
125
+ const body = (await res.json()) as TrovesStrategiesApiPayload;
126
+ const row = body.strategies?.find((s) => s.id === this.config.trovesStrategyId);
127
+ if (!row) {
128
+ logger.warn(
129
+ `${SvkTrovesAdapter.name}::getAPY: strategy id not found: ${this.config.trovesStrategyId}`,
130
+ );
131
+ const fallback = { apy: 0, type: APYType.BASE };
132
+ this.setCache(CACHE_KEY, fallback, 300_000);
133
+ return fallback;
134
+ }
135
+ const apy = parseTrovesApyField(row.apy);
136
+ const result: PositionAPY = { apy, type: APYType.BASE };
137
+ this.setCache(CACHE_KEY, result, 300_000);
138
+ return result;
139
+ } catch (error) {
140
+ logger.error(`${SvkTrovesAdapter.name}::getAPY:`, error);
141
+ throw error;
142
+ }
143
+ }
144
+
145
+ protected async getPosition(supportedPosition: SupportedPosition): Promise<PositionAmount | null> {
146
+ const CACHE_KEY = `svk_pos_${this.config.strategyVault.address}_${this._positionOwner().address}`;
147
+ const cached = this.getCache<PositionAmount>(CACHE_KEY);
148
+ if (cached) {
149
+ return cached;
150
+ }
151
+
152
+ try {
153
+ const vault = new Contract({
154
+ abi: universalVaultAbi as never,
155
+ address: this.config.strategyVault.address,
156
+ providerOrAccount: this.config.networkConfig.provider,
157
+ });
158
+
159
+ const owner = this._positionOwner();
160
+ const decimals = supportedPosition.asset.decimals;
161
+ const shares = await vault.balance_of(owner.address);
162
+ const shareU256 = uint256.bnToUint256(shares);
163
+ const liquidAssetsRaw: any = await vault.convert_to_assets(shareU256);
164
+ const liquid = Web3Number.fromWei(liquidAssetsRaw.toString(), decimals);
165
+
166
+ let pending = Web3Number.fromWei("0", decimals);
167
+ try {
168
+ const dueRaw: any = await vault.call("due_assets_from_owner", [owner.address]);
169
+ pending = Web3Number.fromWei(dueRaw.toString(), decimals);
170
+ } catch (e) {
171
+ logger.warn(
172
+ `${SvkTrovesAdapter.name}::getPosition: due_assets_from_owner failed (treating as 0): ${(e as Error).message}`,
173
+ );
174
+ }
175
+
176
+ const total = liquid.plus(pending);
177
+ const remarks = `Troves ${this.config.trovesStrategyId} holdings`
178
+
179
+ const result: PositionAmount = {
180
+ amount: total,
181
+ remarks,
182
+ };
183
+
184
+ this.setCache(CACHE_KEY, result, 60_000);
185
+ return result;
186
+ } catch (error) {
187
+ logger.error(`${SvkTrovesAdapter.name}::getPosition:`, error);
188
+ throw error;
189
+ }
190
+ }
191
+
192
+ async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
193
+ const baseToken = this.config.baseToken;
194
+ if (!amount) {
195
+ return {
196
+ tokenInfo: baseToken,
197
+ amount: new Web3Number("999999999999999999999999999", baseToken.decimals),
198
+ usdValue: 999999999999999999999999999,
199
+ remarks: "Max deposit (unbounded placeholder)",
200
+ apy: await this.getAPY({ asset: baseToken, isDebt: false }),
201
+ protocol: this.protocol,
202
+ };
203
+ }
204
+ const usdValue = await this.getUSDValue(baseToken, amount);
205
+ return {
206
+ tokenInfo: baseToken,
207
+ amount,
208
+ usdValue,
209
+ remarks: "Deposit amount",
210
+ apy: await this.getAPY({ asset: baseToken, isDebt: false }),
211
+ protocol: this.protocol,
212
+ };
213
+ }
214
+
215
+ async maxWithdraw(): Promise<PositionInfo> {
216
+ const baseToken = this.config.baseToken;
217
+ const current = await this.getPosition({ asset: baseToken, isDebt: false });
218
+ const pos = current ?? { amount: new Web3Number("0", baseToken.decimals), remarks: "" };
219
+ const usdValue = await this.getUSDValue(baseToken, pos.amount);
220
+ return {
221
+ tokenInfo: baseToken,
222
+ amount: pos.amount,
223
+ usdValue,
224
+ remarks: "Max withdraw (liquid + pending redemption, underlying units)",
225
+ apy: await this.getAPY({ asset: baseToken, isDebt: false }),
226
+ protocol: this.protocol,
227
+ };
228
+ }
229
+
230
+ protected _getDepositLeaf(): {
231
+ target: ContractAddr;
232
+ method: string;
233
+ packedArguments: bigint[];
234
+ sanitizer: ContractAddr;
235
+ id: string;
236
+ }[] {
237
+ const baseToken = this.config.baseToken;
238
+ const strategyVault = this.config.strategyVault;
239
+ const receiver = this.config.vaultAllocator;
240
+
241
+ return [
242
+ {
243
+ target: baseToken.address,
244
+ method: "approve",
245
+ packedArguments: [strategyVault.toBigInt()],
246
+ sanitizer: SIMPLE_SANITIZER,
247
+ id: this._depositApproveProofReadableId(),
248
+ },
249
+ {
250
+ target: strategyVault,
251
+ method: "deposit",
252
+ packedArguments: [receiver.toBigInt()],
253
+ sanitizer: SIMPLE_SANITIZER,
254
+ id: this._depositCallProofReadableId(),
255
+ },
256
+ ];
257
+ }
258
+
259
+ protected _getWithdrawLeaf(): {
260
+ target: ContractAddr;
261
+ method: string;
262
+ packedArguments: bigint[];
263
+ sanitizer: ContractAddr;
264
+ id: string;
265
+ }[] {
266
+ const strategyVault = this.config.strategyVault;
267
+ const recv = this.config.vaultAllocator;
268
+ const owner = this.config.vaultAllocator;
269
+
270
+ return [
271
+ {
272
+ target: strategyVault,
273
+ method: "withdraw",
274
+ packedArguments: [recv.toBigInt(), owner.toBigInt()],
275
+ sanitizer: SIMPLE_SANITIZER,
276
+ id: this._withdrawCallProofReadableId(),
277
+ },
278
+ ];
279
+ }
280
+
281
+ getDepositAdapter(): AdapterLeafType<DepositParams> {
282
+ const leafConfigs = this._getDepositLeaf();
283
+ const leaves = leafConfigs.map((config) => {
284
+ const { target, method, packedArguments, sanitizer, id } = config;
285
+ return this.constructSimpleLeafData({ id, target, method, packedArguments }, sanitizer);
286
+ });
287
+ return { leaves, callConstructor: this.getDepositCall.bind(this) as unknown as GenerateCallFn<DepositParams> };
288
+ }
289
+
290
+ getWithdrawAdapter(): AdapterLeafType<WithdrawParams> {
291
+ const leafConfigs = this._getWithdrawLeaf();
292
+ const leaves = leafConfigs.map((config) => {
293
+ const { target, method, packedArguments, sanitizer, id } = config;
294
+ return this.constructSimpleLeafData({ id, target, method, packedArguments }, sanitizer);
295
+ });
296
+ return { leaves, callConstructor: this.getWithdrawCall.bind(this) as unknown as GenerateCallFn<WithdrawParams> };
297
+ }
298
+
299
+ async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
300
+ const baseToken = this.config.baseToken;
301
+ const strategyVault = this.config.strategyVault;
302
+ const amount = params.amount;
303
+ const uint256Amount = uint256.bnToUint256(amount.toWei());
304
+ const receiver = this.config.vaultAllocator;
305
+
306
+ return [
307
+ {
308
+ proofReadableId: this._depositApproveProofReadableId(),
309
+ sanitizer: SIMPLE_SANITIZER,
310
+ call: {
311
+ contractAddress: baseToken.address,
312
+ selector: hash.getSelectorFromName("approve"),
313
+ calldata: [
314
+ strategyVault.toBigInt(),
315
+ toBigInt(uint256Amount.low.toString()),
316
+ toBigInt(uint256Amount.high.toString()),
317
+ ],
318
+ },
319
+ },
320
+ {
321
+ proofReadableId: this._depositCallProofReadableId(),
322
+ sanitizer: SIMPLE_SANITIZER,
323
+ call: {
324
+ contractAddress: strategyVault,
325
+ selector: hash.getSelectorFromName("deposit"),
326
+ calldata: [
327
+ toBigInt(uint256Amount.low.toString()),
328
+ toBigInt(uint256Amount.high.toString()),
329
+ receiver.toBigInt(),
330
+ ],
331
+ },
332
+ },
333
+ ];
334
+ }
335
+
336
+ async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
337
+ const strategyVault = this.config.strategyVault;
338
+ const amount = params.amount;
339
+ const uint256Amount = uint256.bnToUint256(amount.toWei());
340
+ const recv = this.config.vaultAllocator;
341
+ const owner = this.config.vaultAllocator;
342
+
343
+ return [
344
+ {
345
+ proofReadableId: this._withdrawCallProofReadableId(),
346
+ sanitizer: SIMPLE_SANITIZER,
347
+ call: {
348
+ contractAddress: strategyVault,
349
+ selector: hash.getSelectorFromName("withdraw"),
350
+ calldata: [
351
+ toBigInt(uint256Amount.low.toString()),
352
+ toBigInt(uint256Amount.high.toString()),
353
+ recv.toBigInt(),
354
+ owner.toBigInt(),
355
+ ],
356
+ },
357
+ },
358
+ ];
359
+ }
360
+
361
+ getHealthFactor(): Promise<number> {
362
+ return Promise.resolve(10);
363
+ }
364
+ }
@@ -0,0 +1,200 @@
1
+ import { ContractAddr, Web3Number } from "@/dataTypes";
2
+ import {
3
+ APYType,
4
+ BaseAdapter,
5
+ BaseAdapterConfig,
6
+ DepositParams,
7
+ ManageCall,
8
+ PositionAmount,
9
+ PositionAPY,
10
+ PositionInfo,
11
+ SupportedPosition,
12
+ WithdrawParams,
13
+ } from "./baseAdapter";
14
+ import { hash, uint256 } from "starknet";
15
+ import { ERC20, TokenMarketData } from "@/modules";
16
+ import { Protocols } from "@/interfaces";
17
+ import { SIMPLE_SANITIZER, toBigInt, TRANSFER_SANITIZER } from "./adapter-utils";
18
+ import { logger } from "@/utils";
19
+
20
+ export interface TokenTransferAdapterConfig extends BaseAdapterConfig {
21
+ /** Address that funds are sent FROM during deposit (and returned TO during withdraw) */
22
+ fromAddress: ContractAddr;
23
+ /** Address that funds are sent TO during deposit (and pulled FROM during withdraw) */
24
+ toAddress: ContractAddr;
25
+ }
26
+
27
+ /**
28
+ * Adapter for transferring a single token between two fixed addresses.
29
+ *
30
+ * Deposit: transfers baseToken from `fromAddress` → `toAddress`
31
+ * Withdraw: transfers baseToken from `toAddress` → `fromAddress` (requires toAddress to approve fromAddress/VA)
32
+ *
33
+ * Proof IDs are derived from `tr_<symbol>_<toAddrShort>` to be unique per token+destination pair.
34
+ */
35
+ export class TokenTransferAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
36
+ readonly config: TokenTransferAdapterConfig;
37
+ readonly tokenMarketData: TokenMarketData;
38
+
39
+ constructor(config: TokenTransferAdapterConfig) {
40
+ super(config, TokenTransferAdapter.name, Protocols.NONE);
41
+ this.config = config;
42
+ this.tokenMarketData = new TokenMarketData(this.config.pricer, this.config.networkConfig);
43
+ }
44
+
45
+ private _idBase(): string {
46
+ return `tr_${this.config.baseToken.symbol}_${this.config.toAddress.shortString()}`;
47
+ }
48
+
49
+ private _depositCallProofReadableId(): string {
50
+ return `${this._idBase()}`;
51
+ }
52
+
53
+ private _withdrawCallProofReadableId(): string {
54
+ return `tr_wd_${this.config.baseToken.symbol}_${this.config.toAddress.shortString()}`;
55
+ }
56
+
57
+ protected async getAPY(_supportedPosition: SupportedPosition): Promise<PositionAPY> {
58
+ const isSupported = this.tokenMarketData.isAPYSupported(this.config.baseToken);
59
+ const apy = isSupported ? await this.tokenMarketData.getAPY(this.config.baseToken) : 0;
60
+ return { apy, type: isSupported ? APYType.LST : APYType.BASE };
61
+ }
62
+
63
+ protected async getPosition(supportedPosition: SupportedPosition): Promise<PositionAmount> {
64
+ // only measure balance of toAddress, bcz fromAddress usually gets trakced in unused balance or a previous token transfer adapter
65
+ try {
66
+ const balance = await new ERC20(this.config.networkConfig).balanceOf(
67
+ supportedPosition.asset.address,
68
+ this.config.toAddress.address,
69
+ supportedPosition.asset.decimals,
70
+ );
71
+ return { amount: balance, remarks: `Unused balance [${this.config.toAddress.shortString()}]` };
72
+ } catch (_e) {
73
+ logger.error(`${TokenTransferAdapter.name}::getPosition: failed for ${supportedPosition.asset.symbol}`);
74
+ throw new Error(`${TokenTransferAdapter.name}: failed to get balance for ${supportedPosition.asset.symbol}`);
75
+ }
76
+ }
77
+
78
+ async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
79
+ const baseToken = this.config.baseToken;
80
+ const fromBalance = await new ERC20(this.config.networkConfig).balanceOf(
81
+ baseToken.address,
82
+ this.config.fromAddress.address,
83
+ baseToken.decimals,
84
+ );
85
+ const depositable = amount && amount.toNumber() <= fromBalance.toNumber() ? amount : fromBalance;
86
+ const usdValue = await this.getUSDValue(baseToken, depositable);
87
+ return {
88
+ tokenInfo: baseToken,
89
+ amount: depositable,
90
+ usdValue,
91
+ remarks: "Max deposit (from-address balance)",
92
+ apy: await this.getAPY({ asset: baseToken, isDebt: false }),
93
+ protocol: this.protocol,
94
+ };
95
+ }
96
+
97
+ async maxWithdraw(): Promise<PositionInfo> {
98
+ const baseToken = this.config.baseToken;
99
+ const toBalance = await new ERC20(this.config.networkConfig).balanceOf(
100
+ baseToken.address,
101
+ this.config.toAddress.address,
102
+ baseToken.decimals,
103
+ );
104
+ const usdValue = await this.getUSDValue(baseToken, toBalance);
105
+ return {
106
+ tokenInfo: baseToken,
107
+ amount: toBalance,
108
+ usdValue,
109
+ remarks: "Max withdraw (to-address balance)",
110
+ apy: await this.getAPY({ asset: baseToken, isDebt: false }),
111
+ protocol: this.protocol,
112
+ };
113
+ }
114
+
115
+ protected _getDepositLeaf(): {
116
+ target: ContractAddr;
117
+ method: string;
118
+ packedArguments: bigint[];
119
+ sanitizer: ContractAddr;
120
+ id: string;
121
+ }[] {
122
+ return [
123
+ {
124
+ target: this.config.baseToken.address,
125
+ method: "transfer",
126
+ packedArguments: [this.config.toAddress.toBigInt()],
127
+ sanitizer: TRANSFER_SANITIZER,
128
+ id: this._depositCallProofReadableId(),
129
+ },
130
+ ];
131
+ }
132
+
133
+ protected _getWithdrawLeaf(): {
134
+ target: ContractAddr;
135
+ method: string;
136
+ packedArguments: bigint[];
137
+ sanitizer: ContractAddr;
138
+ id: string;
139
+ }[] {
140
+ // note, to address should have given allowance to from address
141
+ return [
142
+ {
143
+ target: this.config.baseToken.address,
144
+ method: "transfer_from",
145
+ packedArguments: [
146
+ this.config.toAddress.toBigInt(), // from
147
+ this.config.fromAddress.toBigInt(), // to
148
+ ],
149
+ sanitizer: TRANSFER_SANITIZER,
150
+ id: this._withdrawCallProofReadableId(),
151
+ },
152
+ ];
153
+ }
154
+
155
+ async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
156
+ const amount = params.amount;
157
+ const uint256Amount = uint256.bnToUint256(amount.toWei());
158
+ return [
159
+ {
160
+ proofReadableId: this._depositCallProofReadableId(),
161
+ sanitizer: TRANSFER_SANITIZER,
162
+ call: {
163
+ contractAddress: this.config.baseToken.address,
164
+ selector: hash.getSelectorFromName("transfer"),
165
+ calldata: [
166
+ this.config.toAddress.toBigInt(),
167
+ toBigInt(uint256Amount.low.toString()),
168
+ toBigInt(uint256Amount.high.toString()),
169
+ ],
170
+ },
171
+ },
172
+ ];
173
+ }
174
+
175
+ async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
176
+ const amount = params.amount;
177
+ const uint256Amount = uint256.bnToUint256(amount.toWei());
178
+ // note, from address should have given allowance to to address
179
+ return [
180
+ {
181
+ proofReadableId: this._withdrawCallProofReadableId(),
182
+ sanitizer: TRANSFER_SANITIZER,
183
+ call: {
184
+ contractAddress: this.config.baseToken.address,
185
+ selector: hash.getSelectorFromName("transfer_from"),
186
+ calldata: [
187
+ this.config.toAddress.toBigInt(), // from
188
+ this.config.fromAddress.toBigInt(), // to
189
+ toBigInt(uint256Amount.low.toString()),
190
+ toBigInt(uint256Amount.high.toString()),
191
+ ],
192
+ },
193
+ },
194
+ ];
195
+ }
196
+
197
+ async getHealthFactor(): Promise<number> {
198
+ return Promise.resolve(10);
199
+ }
200
+ }