@strkfarm/sdk 1.0.28 → 1.0.30
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 +48 -26
- package/dist/cli.mjs +45 -23
- package/dist/index.browser.global.js +9857 -326
- package/dist/index.browser.mjs +9640 -108
- package/dist/index.d.ts +65 -16
- package/dist/index.js +9654 -121
- package/dist/index.mjs +9642 -110
- package/package.json +1 -1
- package/src/data/vesu_pools.json +9019 -0
- package/src/dataTypes/_bignumber.ts +15 -7
- package/src/global.ts +13 -6
- package/src/interfaces/common.ts +3 -0
- package/src/modules/avnu.ts +78 -59
- package/src/modules/harvests.ts +111 -0
- package/src/modules/pricer-from-api.ts +9 -8
- package/src/modules/zkLend.ts +2 -1
- package/src/strategies/base-strategy.ts +3 -3
- package/src/strategies/ekubo-cl-vault.ts +477 -55
- package/src/strategies/index.ts +2 -1
- package/src/strategies/vesu-rebalance.ts +77 -14
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logger } from "@/global";
|
|
1
2
|
import BigNumber from "bignumber.js";
|
|
2
3
|
|
|
3
4
|
export class _Web3Number<T extends _Web3Number<T>> extends BigNumber {
|
|
@@ -13,22 +14,22 @@ export class _Web3Number<T extends _Web3Number<T>> extends BigNumber {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
multipliedBy(value: string | number | T): T {
|
|
16
|
-
|
|
17
|
+
const _value = this.getStandardString(value);
|
|
17
18
|
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
dividedBy(value: string | number | T): T {
|
|
21
|
-
|
|
22
|
+
const _value = this.getStandardString(value);
|
|
22
23
|
return this.construct(this.div(_value).toString(), this.decimals);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
plus(value: string | number | T): T {
|
|
26
|
-
const _value =
|
|
27
|
+
const _value = this.getStandardString(value);
|
|
27
28
|
return this.construct(this.add(_value).toString(), this.decimals);
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
minus(n: number | string | T, base?: number): T {
|
|
31
|
-
const _value =
|
|
32
|
+
const _value = this.getStandardString(n);
|
|
32
33
|
return this.construct(super.minus(_value, base).toString(), this.decimals);
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -49,9 +50,16 @@ export class _Web3Number<T extends _Web3Number<T>> extends BigNumber {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
private maxToFixedDecimals() {
|
|
52
|
-
return Math.min(this.decimals,
|
|
53
|
+
return Math.min(this.decimals, 18);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private getStandardString(value: string | number | T): string {
|
|
57
|
+
if (typeof value == 'string') {
|
|
58
|
+
return value
|
|
59
|
+
}
|
|
60
|
+
return value.toFixed(this.maxToFixedDecimals())
|
|
53
61
|
}
|
|
54
62
|
}
|
|
55
63
|
|
|
56
|
-
BigNumber.config({ DECIMAL_PLACES: 18 })
|
|
57
|
-
_Web3Number.config({ DECIMAL_PLACES: 18 })
|
|
64
|
+
BigNumber.config({ DECIMAL_PLACES: 18, ROUNDING_MODE: BigNumber.ROUND_DOWN })
|
|
65
|
+
_Web3Number.config({ DECIMAL_PLACES: 18, ROUNDING_MODE: BigNumber.ROUND_DOWN })
|
package/src/global.ts
CHANGED
|
@@ -52,42 +52,48 @@ const defaultTokens: TokenInfo[] = [{
|
|
|
52
52
|
logo: 'https://assets.coingecko.com/coins/images/26433/small/starknet.png',
|
|
53
53
|
address: ContractAddr.from('0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d'),
|
|
54
54
|
decimals: 18,
|
|
55
|
-
coingeckId: 'starknet'
|
|
55
|
+
coingeckId: 'starknet',
|
|
56
|
+
displayDecimals: 2,
|
|
56
57
|
}, {
|
|
57
58
|
name: 'xSTRK',
|
|
58
59
|
symbol: 'xSTRK',
|
|
59
60
|
logo: 'https://dashboard.endur.fi/endur-fi.svg',
|
|
60
61
|
address: ContractAddr.from('0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a'),
|
|
61
62
|
decimals: 18,
|
|
62
|
-
coingeckId: undefined
|
|
63
|
+
coingeckId: undefined,
|
|
64
|
+
displayDecimals: 2,
|
|
63
65
|
}, {
|
|
64
66
|
name: 'ETH',
|
|
65
67
|
symbol: 'ETH',
|
|
66
68
|
logo: 'https://opbnb.bscscan.com/token/images/ether.svg',
|
|
67
69
|
address: ContractAddr.from('0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7'),
|
|
68
70
|
decimals: 18,
|
|
69
|
-
coingeckId: undefined
|
|
71
|
+
coingeckId: undefined,
|
|
72
|
+
displayDecimals: 4,
|
|
70
73
|
}, {
|
|
71
74
|
name: 'USDC',
|
|
72
75
|
symbol: 'USDC',
|
|
73
76
|
logo: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png',
|
|
74
77
|
address: ContractAddr.from('0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8'),
|
|
75
78
|
decimals: 6,
|
|
76
|
-
coingeckId: undefined
|
|
79
|
+
coingeckId: undefined,
|
|
80
|
+
displayDecimals: 2,
|
|
77
81
|
}, {
|
|
78
82
|
name: 'USDT',
|
|
79
83
|
symbol: 'USDT',
|
|
80
84
|
logo: 'https://assets.coingecko.com/coins/images/325/small/Tether.png',
|
|
81
85
|
address: ContractAddr.from('0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8'),
|
|
82
86
|
decimals: 6,
|
|
83
|
-
coingeckId: undefined
|
|
87
|
+
coingeckId: undefined,
|
|
88
|
+
displayDecimals: 2,
|
|
84
89
|
}, {
|
|
85
90
|
name: 'WBTC',
|
|
86
91
|
symbol: 'WBTC',
|
|
87
92
|
logo: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png',
|
|
88
93
|
address: ContractAddr.from('0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac'),
|
|
89
94
|
decimals: 8,
|
|
90
|
-
coingeckId: undefined
|
|
95
|
+
coingeckId: undefined,
|
|
96
|
+
displayDecimals: 6,
|
|
91
97
|
}]
|
|
92
98
|
const tokens: TokenInfo[] = defaultTokens;
|
|
93
99
|
|
|
@@ -150,6 +156,7 @@ export class Global {
|
|
|
150
156
|
decimals: token.decimals,
|
|
151
157
|
logo: token.logoUri,
|
|
152
158
|
coingeckId: token.extensions.coingeckoId,
|
|
159
|
+
displayDecimals: 2
|
|
153
160
|
});
|
|
154
161
|
});
|
|
155
162
|
console.log(tokens);
|
package/src/interfaces/common.ts
CHANGED
|
@@ -29,6 +29,7 @@ export interface TokenInfo {
|
|
|
29
29
|
decimals: number,
|
|
30
30
|
logo: string,
|
|
31
31
|
coingeckId?: string,
|
|
32
|
+
displayDecimals: number
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export enum Network {
|
|
@@ -73,10 +74,12 @@ export interface IStrategyMetadata<T> {
|
|
|
73
74
|
netRisk: number,
|
|
74
75
|
notARisks: string[]
|
|
75
76
|
},
|
|
77
|
+
apyMethodology?: string,
|
|
76
78
|
additionalInfo: T
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
export interface IInvestmentFlow {
|
|
82
|
+
id?: string, // used to link flows
|
|
80
83
|
title: string,
|
|
81
84
|
subItems: {key: string, value: string}[],
|
|
82
85
|
linkedFlows: IInvestmentFlow[],
|
package/src/modules/avnu.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { uint256 } from "starknet";
|
|
|
3
3
|
import { Call, Uint256 } from "starknet";
|
|
4
4
|
import { fetchBuildExecuteTransaction, fetchQuotes, Quote } from "@avnu/avnu-sdk";
|
|
5
5
|
import { assert } from "../utils";
|
|
6
|
+
import { logger } from "@/global";
|
|
6
7
|
|
|
7
8
|
export interface Route {
|
|
8
9
|
token_from: string,
|
|
@@ -26,68 +27,86 @@ export interface SwapInfo {
|
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
export class AvnuWrapper {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
async getQuotes(
|
|
31
|
+
fromToken: string,
|
|
32
|
+
toToken: string,
|
|
33
|
+
amountWei: string,
|
|
34
|
+
taker: string,
|
|
35
|
+
retry = 0
|
|
36
|
+
): Promise<Quote> {
|
|
37
|
+
const MAX_RETRY = 5;
|
|
38
|
+
logger.verbose(`${AvnuWrapper.name}: getQuotes => Getting quotes for ${fromToken} -> ${toToken}, amount: ${amountWei}, taker: ${taker}, retry: ${retry}`);
|
|
39
|
+
const params: any = {
|
|
40
|
+
sellTokenAddress: fromToken,
|
|
41
|
+
buyTokenAddress: toToken,
|
|
42
|
+
sellAmount: amountWei,
|
|
43
|
+
takerAddress: taker,
|
|
44
|
+
// excludeSources: ['Nostra', 'Haiko(Solvers)']
|
|
45
|
+
excludeSources: ['Haiko(Solvers)'] // to resolve InvalidOraclePrice error
|
|
46
|
+
};
|
|
47
|
+
assert(fromToken != toToken, "From and to tokens are the same");
|
|
42
48
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
const quotes = await fetchQuotes(params);
|
|
50
|
+
if (quotes.length == 0) {
|
|
51
|
+
if (retry < MAX_RETRY) {
|
|
52
|
+
await new Promise((res) => setTimeout(res, 3000))
|
|
53
|
+
return await this.getQuotes(fromToken, toToken, amountWei, taker, retry + 1);
|
|
54
|
+
}
|
|
55
|
+
throw new Error('no quotes found')
|
|
46
56
|
}
|
|
57
|
+
return quotes[0];
|
|
58
|
+
}
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// use call data to re-construct routes
|
|
63
|
-
let startIndex = 12;
|
|
64
|
-
const routes: Route[] = [];
|
|
65
|
-
for(let i=0; i<routesLen; ++i) {
|
|
66
|
-
const swap_params_len = Number(callData[startIndex + 4]);
|
|
67
|
-
const route: Route = {
|
|
68
|
-
token_from: callData[startIndex],
|
|
69
|
-
token_to: callData[startIndex + 1],
|
|
70
|
-
exchange_address: callData[startIndex + 2],
|
|
71
|
-
percent: Number(callData[startIndex + 3]),
|
|
72
|
-
additional_swap_params: swap_params_len > 0 ? callData.slice(startIndex + 5, startIndex + 5 + swap_params_len): []
|
|
73
|
-
}
|
|
74
|
-
routes.push(route);
|
|
75
|
-
startIndex += 5 + swap_params_len;
|
|
76
|
-
}
|
|
60
|
+
async getSwapInfo(
|
|
61
|
+
quote: Quote,
|
|
62
|
+
taker: string,
|
|
63
|
+
integratorFeeBps: number,
|
|
64
|
+
integratorFeeRecipient: string,
|
|
65
|
+
minAmount?: string
|
|
66
|
+
) {
|
|
67
|
+
const calldata = await fetchBuildExecuteTransaction(quote.quoteId);
|
|
68
|
+
// its the multi swap function call
|
|
69
|
+
const call: Call = calldata.calls[1];
|
|
70
|
+
const callData: string[] = call.calldata as string[];
|
|
71
|
+
const routesLen: number = Number(callData[11]);
|
|
72
|
+
assert(routesLen > 0, "No routes found");
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
74
|
+
// use call data to re-construct routes
|
|
75
|
+
let startIndex = 12;
|
|
76
|
+
const routes: Route[] = [];
|
|
77
|
+
for (let i = 0; i < routesLen; ++i) {
|
|
78
|
+
const swap_params_len = Number(callData[startIndex + 4]);
|
|
79
|
+
const route: Route = {
|
|
80
|
+
token_from: callData[startIndex],
|
|
81
|
+
token_to: callData[startIndex + 1],
|
|
82
|
+
exchange_address: callData[startIndex + 2],
|
|
83
|
+
percent: Number(callData[startIndex + 3]),
|
|
84
|
+
additional_swap_params:
|
|
85
|
+
swap_params_len > 0
|
|
86
|
+
? callData.slice(startIndex + 5, startIndex + 5 + swap_params_len)
|
|
87
|
+
: [],
|
|
88
|
+
};
|
|
89
|
+
routes.push(route);
|
|
90
|
+
startIndex += 5 + swap_params_len;
|
|
92
91
|
}
|
|
92
|
+
|
|
93
|
+
// swapInfo as expected by the strategy
|
|
94
|
+
// fallback, max 1% slippage
|
|
95
|
+
const _minAmount = minAmount || (quote.buyAmount * 95n / 100n).toString();
|
|
96
|
+
logger.verbose(`${AvnuWrapper.name}: getSwapInfo => buyToken: ${quote.buyTokenAddress}`);
|
|
97
|
+
logger.verbose(`${AvnuWrapper.name}: getSwapInfo => buyAmount: ${quote.buyAmount}, minAmount: ${_minAmount}`);
|
|
98
|
+
const swapInfo: SwapInfo = {
|
|
99
|
+
token_from_address: quote.sellTokenAddress,
|
|
100
|
+
token_from_amount: uint256.bnToUint256(quote.sellAmount),
|
|
101
|
+
token_to_address: quote.buyTokenAddress,
|
|
102
|
+
token_to_amount: uint256.bnToUint256(_minAmount),
|
|
103
|
+
token_to_min_amount: uint256.bnToUint256(_minAmount),
|
|
104
|
+
beneficiary: taker,
|
|
105
|
+
integrator_fee_amount_bps: integratorFeeBps,
|
|
106
|
+
integrator_fee_recipient: integratorFeeRecipient,
|
|
107
|
+
routes,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return swapInfo;
|
|
111
|
+
}
|
|
93
112
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { ContractAddr, Web3Number } from "@/dataTypes";
|
|
2
|
+
import { logger } from "@/global";
|
|
3
|
+
import { IConfig } from "@/interfaces";
|
|
4
|
+
import { assert } from "@/utils";
|
|
5
|
+
import { Contract, num } from "starknet";
|
|
6
|
+
|
|
7
|
+
export interface HarvestInfo {
|
|
8
|
+
rewardsContract: ContractAddr,
|
|
9
|
+
token: ContractAddr,
|
|
10
|
+
startDate: Date,
|
|
11
|
+
endDate: Date,
|
|
12
|
+
claim: {
|
|
13
|
+
id: number,
|
|
14
|
+
amount: Web3Number,
|
|
15
|
+
claimee: ContractAddr
|
|
16
|
+
},
|
|
17
|
+
actualReward: Web3Number,
|
|
18
|
+
proof: string[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class Harvests {
|
|
22
|
+
constructor(protected readonly config: IConfig) {}
|
|
23
|
+
|
|
24
|
+
getHarvests(addr: ContractAddr): Promise<HarvestInfo[]> {
|
|
25
|
+
throw new Error("Not implemented");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async getUnHarvestedRewards(addr: ContractAddr) {
|
|
29
|
+
const rewards = await this.getHarvests(addr);
|
|
30
|
+
if (rewards.length == 0) return [];
|
|
31
|
+
|
|
32
|
+
const unClaimed: HarvestInfo[] = [];
|
|
33
|
+
|
|
34
|
+
const cls = await this.config.provider.getClassAt(rewards[0].rewardsContract.address);
|
|
35
|
+
for (let reward of rewards) {
|
|
36
|
+
const contract = new Contract(cls.abi, reward.rewardsContract.address, this.config.provider);
|
|
37
|
+
const isClaimed = await contract.call('is_claimed', [reward.claim.id]);
|
|
38
|
+
logger.verbose(`${Harvests.name}: isClaimed: ${isClaimed}`);
|
|
39
|
+
if (isClaimed)
|
|
40
|
+
return unClaimed;
|
|
41
|
+
unClaimed.unshift(reward); // to ensure older harvest is first
|
|
42
|
+
}
|
|
43
|
+
return unClaimed;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const STRK = '0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d';
|
|
48
|
+
|
|
49
|
+
export class EkuboHarvests extends Harvests {
|
|
50
|
+
async getHarvests(addr: ContractAddr) {
|
|
51
|
+
const EKUBO_API = `https://starknet-mainnet-api.ekubo.org/airdrops/${addr.address}?token=${STRK}`
|
|
52
|
+
const resultEkubo = await fetch(EKUBO_API);
|
|
53
|
+
const items = (await resultEkubo.json());
|
|
54
|
+
|
|
55
|
+
const rewards: HarvestInfo[] = [];
|
|
56
|
+
for (let i=0; i<items.length; ++i) {
|
|
57
|
+
const info = items[i];
|
|
58
|
+
assert(info.token == STRK, 'expected strk token only')
|
|
59
|
+
rewards.push({
|
|
60
|
+
rewardsContract: ContractAddr.from(info.contract_address),
|
|
61
|
+
token: ContractAddr.from(STRK),
|
|
62
|
+
startDate: new Date(info.start_date),
|
|
63
|
+
endDate: new Date(info.end_date),
|
|
64
|
+
claim: {
|
|
65
|
+
id: info.claim.id,
|
|
66
|
+
amount: Web3Number.fromWei(info.claim.amount, 18),
|
|
67
|
+
claimee: ContractAddr.from(info.claim.claimee)
|
|
68
|
+
},
|
|
69
|
+
actualReward: Web3Number.fromWei(info.claim.amount, 18),
|
|
70
|
+
proof: info.proof
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime());
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class VesuHarvests extends Harvests {
|
|
78
|
+
async getHarvests(addr: ContractAddr): Promise<HarvestInfo[]> {
|
|
79
|
+
const result = await fetch(`https://api.vesu.xyz/users/${addr.address}/strk-rewards/calldata`);
|
|
80
|
+
const data = await result.json();
|
|
81
|
+
const rewardsContract = ContractAddr.from('0x0387f3eb1d98632fbe3440a9f1385Aec9d87b6172491d3Dd81f1c35A7c61048F');
|
|
82
|
+
|
|
83
|
+
// get already claimed amount
|
|
84
|
+
const cls = await this.config.provider.getClassAt(rewardsContract.address);
|
|
85
|
+
const contract = new Contract(cls.abi, rewardsContract.address, this.config.provider);
|
|
86
|
+
const _claimed_amount: any = await contract.call('amount_already_claimed', [addr.address]);
|
|
87
|
+
const claimed_amount = Web3Number.fromWei(_claimed_amount.toString(), 18);
|
|
88
|
+
logger.verbose(`${VesuHarvests.name}: claimed_amount: ${claimed_amount.toString()}`);
|
|
89
|
+
|
|
90
|
+
// get the actual reward
|
|
91
|
+
const actualReward = Web3Number.fromWei(data.data.amount, 18).minus(claimed_amount);
|
|
92
|
+
logger.verbose(`${VesuHarvests.name}: actualReward: ${actualReward.toString()}`);
|
|
93
|
+
return [{
|
|
94
|
+
rewardsContract,
|
|
95
|
+
token: ContractAddr.from(STRK),
|
|
96
|
+
startDate: new Date(0),
|
|
97
|
+
endDate: new Date(0),
|
|
98
|
+
claim: {
|
|
99
|
+
id: 0,
|
|
100
|
+
amount: Web3Number.fromWei(num.getDecimalString(data.data.amount), 18),
|
|
101
|
+
claimee: addr
|
|
102
|
+
},
|
|
103
|
+
actualReward,
|
|
104
|
+
proof: data.data.proof
|
|
105
|
+
}]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async getUnHarvestedRewards(addr: ContractAddr) {
|
|
109
|
+
return await this.getHarvests(addr);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -12,8 +12,8 @@ export class PricerFromApi extends PricerBase {
|
|
|
12
12
|
async getPrice(tokenSymbol: string): Promise<PriceInfo> {
|
|
13
13
|
try {
|
|
14
14
|
return await this.getPriceFromMyAPI(tokenSymbol);
|
|
15
|
-
} catch (e) {
|
|
16
|
-
logger.warn('getPriceFromMyAPI error', e);
|
|
15
|
+
} catch (e: any) {
|
|
16
|
+
logger.warn('getPriceFromMyAPI error', JSON.stringify(e.message || e));
|
|
17
17
|
}
|
|
18
18
|
logger.log('getPrice coinbase', tokenSymbol);
|
|
19
19
|
let retry = 0;
|
|
@@ -32,8 +32,8 @@ export class PricerFromApi extends PricerBase {
|
|
|
32
32
|
price,
|
|
33
33
|
timestamp: new Date()
|
|
34
34
|
}
|
|
35
|
-
} catch (e) {
|
|
36
|
-
logger.warn('getPrice coinbase error', e
|
|
35
|
+
} catch (e: any) {
|
|
36
|
+
logger.warn('getPrice coinbase error', JSON.stringify(e.message || e));
|
|
37
37
|
await new Promise((resolve) => setTimeout(resolve, retry * 1000));
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -48,10 +48,11 @@ export class PricerFromApi extends PricerBase {
|
|
|
48
48
|
const priceInfo = await priceInfoRes.json();
|
|
49
49
|
const now = new Date();
|
|
50
50
|
const priceTime = new Date(priceInfo.timestamp);
|
|
51
|
-
if (now.getTime() - priceTime.getTime() > 900000) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
// if (now.getTime() - priceTime.getTime() > 900000) {
|
|
52
|
+
// // 15 mins
|
|
53
|
+
// logger.verbose(`Price is stale: ${tokenSymbol}, timestamp: ${priceInfo.timestamp}, price: ${priceInfo.price}`);
|
|
54
|
+
// throw new Error('Price is stale');
|
|
55
|
+
// }
|
|
55
56
|
const price = Number(priceInfo.price);
|
|
56
57
|
return {
|
|
57
58
|
price,
|
package/src/modules/zkLend.ts
CHANGED
|
@@ -40,7 +40,8 @@ export class ZkLend extends ILending implements ILending {
|
|
|
40
40
|
logo: '',
|
|
41
41
|
decimals: pool.token.decimals,
|
|
42
42
|
borrowFactor: Web3Number.fromWei(pool.borrow_factor.value, pool.borrow_factor.decimals),
|
|
43
|
-
collareralFactor
|
|
43
|
+
collareralFactor,
|
|
44
|
+
displayDecimals: 2
|
|
44
45
|
}
|
|
45
46
|
this.tokens.push(token);
|
|
46
47
|
});
|
|
@@ -16,7 +16,7 @@ export interface DualActionAmount {
|
|
|
16
16
|
token1: SingleActionAmount
|
|
17
17
|
}
|
|
18
18
|
export interface DualTokenInfo {
|
|
19
|
-
|
|
19
|
+
usdValue: number,
|
|
20
20
|
token0: SingleTokenInfo,
|
|
21
21
|
token1: SingleTokenInfo
|
|
22
22
|
}
|
|
@@ -36,11 +36,11 @@ export class BaseStrategy<TVLInfo, ActionInfo> {
|
|
|
36
36
|
throw new Error("Not implemented");
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
depositCall(amountInfo: ActionInfo, receiver: ContractAddr): Call[] {
|
|
39
|
+
async depositCall(amountInfo: ActionInfo, receiver: ContractAddr): Promise<Call[]> {
|
|
40
40
|
throw new Error("Not implemented");
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
withdrawCall(amountInfo: ActionInfo, receiver: ContractAddr, owner: ContractAddr): Call[] {
|
|
43
|
+
async withdrawCall(amountInfo: ActionInfo, receiver: ContractAddr, owner: ContractAddr): Promise<Call[]> {
|
|
44
44
|
throw new Error("Not implemented");
|
|
45
45
|
}
|
|
46
46
|
|