@gearbox-protocol/sdk 8.2.1 → 8.3.0-next.2
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/cjs/dev/AccountOpener.js +3 -3
- package/dist/cjs/plugins/adapters/BalancerV2VaultAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/BalancerV3RouterAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/CamelotV3AdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/ConvexV1BaseRewardPoolAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/ConvexV1BoosterAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/Curve2AssetsAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/Curve3AssetsAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/Curve4AssetsAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/CurveV1AdapterDeposit.js +1 -1
- package/dist/cjs/plugins/adapters/CurveV1AdapterStETHContract.js +1 -1
- package/dist/cjs/plugins/adapters/CurveV1StableNGAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/DaiUsdsAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/ERC4626AdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/EqualizerRouterAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/MellowERC4626VaultAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/MellowVaultAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/PendleRouterAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/StakingRewardsAdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/UniswapV2AdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/UniswapV3AdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/VelodromeV2AdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/WstETHV1AdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/YearnV2AdapterContract.js +1 -1
- package/dist/cjs/plugins/adapters/index.js +2 -2
- package/dist/cjs/plugins/degen-distributors/DegenDistributorsPlugin.js +1 -1
- package/dist/cjs/plugins/pools-history/Pools7DAgoPlugin.js +1 -1
- package/dist/cjs/sdk/accounts/CreditAccountsService.js +3 -3
- package/dist/cjs/sdk/base/BaseContract.js +2 -2
- package/dist/cjs/sdk/core/address-provider/AbstractAddressProviderContract.js +1 -1
- package/dist/cjs/sdk/index.js +2 -2
- package/dist/cjs/sdk/market/MarketConfiguratorContract.js +1 -1
- package/dist/cjs/sdk/market/MarketRegister.js +42 -33
- package/dist/cjs/sdk/market/MarketSuite.js +5 -8
- package/dist/cjs/sdk/market/pool/PoolSuite.js +2 -2
- package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +25 -0
- package/dist/cjs/sdk/market/pricefeeds/updates/PythUpdater.js +2 -2
- package/dist/cjs/sdk/plugins/V300StalenessPeriodPlugin.js +0 -1
- package/dist/cjs/sdk/router/PathOptionFactory.js +1 -1
- package/dist/cjs/sdk/router/RouterV300Contract.js +1 -1
- package/dist/cjs/sdk/router/RouterV310Contract.js +2 -2
- package/dist/cjs/sdk/sdk-legacy/core/creditAccount.js +37 -17
- package/dist/cjs/sdk/sdk-legacy/core/strategy.js +1 -1
- package/dist/cjs/sdk/sdk-legacy/gearboxRewards/api.js +21 -8
- package/dist/cjs/sdk/sdk-legacy/gearboxRewards/apy.js +20 -17
- package/dist/cjs/sdk/sdk-legacy/gearboxRewards/extraAPY.js +4 -2
- package/dist/cjs/sdk/utils/createRawTx.js +1 -1
- package/dist/cjs/sdk/utils/formatter.js +4 -4
- package/dist/cjs/sdk/utils/viem/simulateWithPriceUpdates.js +2 -2
- package/dist/esm/dev/AccountOpener.js +3 -3
- package/dist/esm/plugins/adapters/BalancerV2VaultAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/BalancerV3RouterAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/CamelotV3AdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/ConvexV1BaseRewardPoolAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/ConvexV1BoosterAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/Curve2AssetsAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/Curve3AssetsAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/Curve4AssetsAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/CurveV1AdapterDeposit.js +1 -1
- package/dist/esm/plugins/adapters/CurveV1AdapterStETHContract.js +1 -1
- package/dist/esm/plugins/adapters/CurveV1StableNGAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/DaiUsdsAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/ERC4626AdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/EqualizerRouterAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/MellowERC4626VaultAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/MellowVaultAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/PendleRouterAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/StakingRewardsAdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/UniswapV2AdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/UniswapV3AdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/VelodromeV2AdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/WstETHV1AdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/YearnV2AdapterContract.js +1 -1
- package/dist/esm/plugins/adapters/index.js +1 -1
- package/dist/esm/plugins/degen-distributors/DegenDistributorsPlugin.js +1 -1
- package/dist/esm/plugins/pools-history/Pools7DAgoPlugin.js +1 -1
- package/dist/esm/sdk/GearboxSDK.js +1 -1
- package/dist/esm/sdk/accounts/CreditAccountsService.js +3 -3
- package/dist/esm/sdk/base/BaseContract.js +2 -2
- package/dist/esm/sdk/core/address-provider/AbstractAddressProviderContract.js +1 -1
- package/dist/esm/sdk/index.js +1 -1
- package/dist/esm/sdk/market/MarketConfiguratorContract.js +1 -1
- package/dist/esm/sdk/market/MarketRegister.js +42 -33
- package/dist/esm/sdk/market/MarketSuite.js +5 -8
- package/dist/esm/sdk/market/pool/PoolSuite.js +2 -2
- package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +25 -0
- package/dist/esm/sdk/market/pricefeeds/updates/PythUpdater.js +2 -2
- package/dist/esm/sdk/plugins/V300StalenessPeriodPlugin.js +0 -1
- package/dist/esm/sdk/router/PathOptionFactory.js +1 -1
- package/dist/esm/sdk/router/RouterV300Contract.js +1 -1
- package/dist/esm/sdk/router/RouterV310Contract.js +2 -2
- package/dist/esm/sdk/sdk-legacy/core/creditAccount.js +37 -17
- package/dist/esm/sdk/sdk-legacy/core/creditSession.js +1 -1
- package/dist/esm/sdk/sdk-legacy/core/strategy.js +1 -1
- package/dist/esm/sdk/sdk-legacy/gearboxRewards/api.js +22 -9
- package/dist/esm/sdk/sdk-legacy/gearboxRewards/apy.js +20 -17
- package/dist/esm/sdk/sdk-legacy/gearboxRewards/extraAPY.js +4 -2
- package/dist/esm/sdk/utils/createRawTx.js +1 -1
- package/dist/esm/sdk/utils/formatter.js +4 -4
- package/dist/esm/sdk/utils/viem/simulateWithPriceUpdates.js +2 -2
- package/dist/types/plugins/adapters/index.d.ts +1 -1
- package/dist/types/plugins/bots/BotsPlugin.d.ts +1 -1
- package/dist/types/sdk/index.d.ts +1 -1
- package/dist/types/sdk/market/MarketRegister.d.ts +3 -7
- package/dist/types/sdk/market/pricefeeds/PriceFeedsRegister.d.ts +13 -1
- package/dist/types/sdk/types/state.d.ts +1 -1
- package/package.json +9 -23
|
@@ -32,7 +32,6 @@ class V300StalenessPeriodPlugin extends import_BasePlugin.BasePlugin {
|
|
|
32
32
|
#syncedTo = 0n;
|
|
33
33
|
#logger;
|
|
34
34
|
#events = [];
|
|
35
|
-
// eslint-disable-next-line accessor-pairs
|
|
36
35
|
set sdk(sdk) {
|
|
37
36
|
super.sdk = sdk;
|
|
38
37
|
this.#syncedTo = import_constants.ADDRESS_PROVIDER_BLOCK[sdk.provider.networkType] - 1n;
|
|
@@ -210,7 +210,7 @@ class RouterV300Contract extends import_AbstractRouterContract.AbstractRouterCon
|
|
|
210
210
|
if (force) {
|
|
211
211
|
this.logger?.warn("applying stkcvxRLUSDUSDC workaround");
|
|
212
212
|
}
|
|
213
|
-
|
|
213
|
+
const results = [];
|
|
214
214
|
for (const po of pathOptions) {
|
|
215
215
|
const { result: result2 } = await this.contract.simulate.findBestClosePath(
|
|
216
216
|
[
|
|
@@ -235,7 +235,7 @@ class RouterV310Contract extends import_AbstractRouterContract.AbstractRouterCon
|
|
|
235
235
|
this.logger?.debug(
|
|
236
236
|
inUSD.map((v) => ({
|
|
237
237
|
token: this.labelAddress(v.token),
|
|
238
|
-
balance: (0, import_formatter.formatBN)(v.balance, 8)
|
|
238
|
+
balance: `${(0, import_formatter.formatBN)(v.balance, 8)} (${v.balance})`
|
|
239
239
|
})),
|
|
240
240
|
"balances in usd"
|
|
241
241
|
);
|
|
@@ -253,7 +253,7 @@ class RouterV310Contract extends import_AbstractRouterContract.AbstractRouterCon
|
|
|
253
253
|
#debugTokenData(tData) {
|
|
254
254
|
return tData.map((t) => ({
|
|
255
255
|
token: this.labelAddress(t.token),
|
|
256
|
-
balance: this.sdk.tokensMeta.formatBN(t.token, t.balance)
|
|
256
|
+
balance: `${this.sdk.tokensMeta.formatBN(t.token, t.balance)} (${t.balance})`,
|
|
257
257
|
leftoverBalance: this.sdk.tokensMeta.formatBN(t.token, t.leftoverBalance) + ` (${t.leftoverBalance})`,
|
|
258
258
|
numSplits: t.numSplits,
|
|
259
259
|
claimRewards: t.claimRewards
|
|
@@ -112,7 +112,7 @@ class CreditAccountData_Legacy {
|
|
|
112
112
|
static sortBalances(balances, prices, tokens) {
|
|
113
113
|
return Object.entries(balances).sort(
|
|
114
114
|
([addr1, amount1], [addr2, amount2]) => {
|
|
115
|
-
return
|
|
115
|
+
return CreditAccountData_Legacy.assetComparator(
|
|
116
116
|
{
|
|
117
117
|
token: addr1,
|
|
118
118
|
balance: amount1
|
|
@@ -131,7 +131,14 @@ class CreditAccountData_Legacy {
|
|
|
131
131
|
}
|
|
132
132
|
static sortAssets(balances, prices, tokens) {
|
|
133
133
|
return balances.sort(
|
|
134
|
-
(t1, t2) =>
|
|
134
|
+
(t1, t2) => CreditAccountData_Legacy.assetComparator(
|
|
135
|
+
t1,
|
|
136
|
+
t2,
|
|
137
|
+
prices,
|
|
138
|
+
prices,
|
|
139
|
+
tokens,
|
|
140
|
+
tokens
|
|
141
|
+
)
|
|
135
142
|
);
|
|
136
143
|
}
|
|
137
144
|
static assetComparator(t1, t2, prices1, prices2, tokens1, tokens2) {
|
|
@@ -152,9 +159,12 @@ class CreditAccountData_Legacy {
|
|
|
152
159
|
token2?.decimals
|
|
153
160
|
);
|
|
154
161
|
if (totalPrice1 === totalPrice2) {
|
|
155
|
-
return t1.balance === t2.balance ?
|
|
162
|
+
return t1.balance === t2.balance ? CreditAccountData_Legacy.tokensAbcComparator(token1, token2) : CreditAccountData_Legacy.amountAbcComparator(t1.balance, t2.balance);
|
|
156
163
|
}
|
|
157
|
-
return
|
|
164
|
+
return CreditAccountData_Legacy.amountAbcComparator(
|
|
165
|
+
totalPrice1,
|
|
166
|
+
totalPrice2
|
|
167
|
+
);
|
|
158
168
|
}
|
|
159
169
|
static tokensAbcComparator(t1, t2) {
|
|
160
170
|
const { symbol: symbol1 = "" } = t1 || {};
|
|
@@ -329,37 +339,43 @@ class CreditAccountData_Legacy {
|
|
|
329
339
|
amount * lt / import_constants.PERCENTAGE_FACTOR
|
|
330
340
|
);
|
|
331
341
|
const recommendedQuota = recommendedBaseQuota * (import_constants.PERCENTAGE_FACTOR + quotaReserve) / import_constants.PERCENTAGE_FACTOR;
|
|
332
|
-
return
|
|
342
|
+
return CreditAccountData_Legacy.roundUpQuota(recommendedQuota);
|
|
333
343
|
}
|
|
334
344
|
static calcDefaultQuota({ amount, lt, quotaReserve }) {
|
|
335
345
|
const recommendedBaseQuota = amount * lt / import_constants.PERCENTAGE_FACTOR;
|
|
336
346
|
const recommendedQuota = recommendedBaseQuota * (import_constants.PERCENTAGE_FACTOR + quotaReserve) / import_constants.PERCENTAGE_FACTOR;
|
|
337
|
-
return
|
|
347
|
+
return CreditAccountData_Legacy.roundUpQuota(recommendedQuota);
|
|
338
348
|
}
|
|
339
349
|
static calcQuotaUpdate(props) {
|
|
340
350
|
const { quotas, initialQuotas, maxDebt, allowedToSpend, allowedToObtain } = props;
|
|
341
351
|
const quotaDecrease = Object.keys(allowedToSpend).reduce((acc, token) => {
|
|
342
|
-
const ch =
|
|
352
|
+
const ch = CreditAccountData_Legacy.getSingleQuotaChange(
|
|
353
|
+
token,
|
|
354
|
+
0n,
|
|
355
|
+
props
|
|
356
|
+
);
|
|
343
357
|
if (ch && ch.balance < 0) acc[ch.token] = ch;
|
|
344
358
|
return acc;
|
|
345
359
|
}, {});
|
|
346
|
-
const quotaCap =
|
|
360
|
+
const quotaCap = CreditAccountData_Legacy.roundUpQuota(maxDebt * 2n);
|
|
347
361
|
const quotaBought = Object.values(initialQuotas).reduce(
|
|
348
|
-
(sum, q) => sum +
|
|
362
|
+
(sum, q) => sum + CreditAccountData_Legacy.roundUpQuota(q?.quota || 0n),
|
|
349
363
|
0n
|
|
350
364
|
);
|
|
351
365
|
const quotaReduced = Object.values(quotaDecrease).reduce((sum, q) => {
|
|
352
366
|
const quotaBalance = q.balance || 0n;
|
|
353
367
|
const safeBalance = quotaBalance === import_constants.MIN_INT96 ? import_math.BigIntMath.neg(
|
|
354
|
-
|
|
368
|
+
CreditAccountData_Legacy.roundUpQuota(
|
|
369
|
+
initialQuotas[q.token]?.quota || 0n
|
|
370
|
+
)
|
|
355
371
|
) : quotaBalance;
|
|
356
372
|
return sum + safeBalance;
|
|
357
373
|
}, 0n);
|
|
358
|
-
const maxQuotaIncrease =
|
|
374
|
+
const maxQuotaIncrease = CreditAccountData_Legacy.roundUpQuota(
|
|
359
375
|
import_math.BigIntMath.max(quotaCap - (quotaBought + quotaReduced), 0n)
|
|
360
376
|
);
|
|
361
377
|
const quotaIncrease = Object.keys(allowedToObtain).reduce((acc, token) => {
|
|
362
|
-
const ch =
|
|
378
|
+
const ch = CreditAccountData_Legacy.getSingleQuotaChange(
|
|
363
379
|
token,
|
|
364
380
|
maxQuotaIncrease,
|
|
365
381
|
props
|
|
@@ -407,19 +423,23 @@ class CreditAccountData_Legacy {
|
|
|
407
423
|
const assetAfter = props.assetsAfterUpdate[token];
|
|
408
424
|
const { amountInTarget = 0n } = assetAfter || {};
|
|
409
425
|
const lt = props.liquidationThresholds[token] || 0n;
|
|
410
|
-
const maxQuotaIncrease =
|
|
411
|
-
|
|
412
|
-
|
|
426
|
+
const maxQuotaIncrease = CreditAccountData_Legacy.roundUpQuota(
|
|
427
|
+
unsafeMaxQuotaIncrease
|
|
428
|
+
);
|
|
429
|
+
const initialQuota = CreditAccountData_Legacy.roundUpQuota(unsafeInitialQuota);
|
|
430
|
+
const defaultQuota = props.calcModification?.type === "recommendedQuota" && props.calcModification.debt > 0 ? CreditAccountData_Legacy.calcRecommendedQuota({
|
|
413
431
|
lt,
|
|
414
432
|
quotaReserve: props.quotaReserve,
|
|
415
433
|
amount: amountInTarget,
|
|
416
434
|
debt: props.calcModification.debt
|
|
417
|
-
}) :
|
|
435
|
+
}) : CreditAccountData_Legacy.calcDefaultQuota({
|
|
418
436
|
lt,
|
|
419
437
|
quotaReserve: props.quotaReserve,
|
|
420
438
|
amount: amountInTarget
|
|
421
439
|
});
|
|
422
|
-
const unsafeQuotaChange =
|
|
440
|
+
const unsafeQuotaChange = CreditAccountData_Legacy.roundUpQuota(
|
|
441
|
+
defaultQuota - initialQuota
|
|
442
|
+
);
|
|
423
443
|
const quotaChange = unsafeQuotaChange > 0 ? import_math.BigIntMath.min(maxQuotaIncrease, unsafeQuotaChange) : unsafeQuotaChange < 0 && import_math.BigIntMath.abs(unsafeQuotaChange) >= initialQuota ? import_constants.MIN_INT96 : unsafeQuotaChange;
|
|
424
444
|
const correctIncrease = assetAfter && props.allowedToObtain[token] && quotaChange > 0;
|
|
425
445
|
const correctDecrease = assetAfter && props.allowedToSpend[token] && quotaChange < 0;
|
|
@@ -24,7 +24,7 @@ module.exports = __toCommonJS(strategy_exports);
|
|
|
24
24
|
var import_constants = require("../../constants/index.js");
|
|
25
25
|
class PositionUtils {
|
|
26
26
|
static maxLeverage(lpToken, cms) {
|
|
27
|
-
const [maxThreshold] =
|
|
27
|
+
const [maxThreshold] = PositionUtils.maxLeverageThreshold(lpToken, cms);
|
|
28
28
|
const maxLeverage = import_constants.PERCENTAGE_FACTOR * import_constants.LEVERAGE_DECIMALS / (import_constants.PERCENTAGE_FACTOR - maxThreshold);
|
|
29
29
|
return Number(maxLeverage - import_constants.LEVERAGE_DECIMALS);
|
|
30
30
|
}
|
|
@@ -51,16 +51,29 @@ class GearboxRewardsApi {
|
|
|
51
51
|
}) {
|
|
52
52
|
if (!airdropDistributorAddress) return [];
|
|
53
53
|
const [claimedRespUnsafe, merkleDataRespUnsafe] = await Promise.allSettled([
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
GearboxRewardsApi.getClaimed({
|
|
55
|
+
airdropDistributorAddress,
|
|
56
|
+
provider,
|
|
57
|
+
account
|
|
58
|
+
}),
|
|
59
|
+
GearboxRewardsApi.getMerkle(
|
|
60
|
+
provider,
|
|
61
|
+
airdropDistributorAddress,
|
|
62
|
+
network,
|
|
63
|
+
account
|
|
64
|
+
)
|
|
56
65
|
]);
|
|
57
|
-
const claimedResp =
|
|
58
|
-
|
|
66
|
+
const claimedResp = GearboxRewardsApi.extractFulfilled(
|
|
67
|
+
claimedRespUnsafe,
|
|
68
|
+
reportError,
|
|
69
|
+
"getLmRewardsV2"
|
|
70
|
+
) || 0n;
|
|
71
|
+
const merkleDataResp = GearboxRewardsApi.extractFulfilled(
|
|
59
72
|
merkleDataRespUnsafe,
|
|
60
73
|
reportError,
|
|
61
74
|
"getLmRewardsV2"
|
|
62
75
|
);
|
|
63
|
-
const amountOnContract =
|
|
76
|
+
const amountOnContract = GearboxRewardsApi.getAmountOnContract({
|
|
64
77
|
account,
|
|
65
78
|
merkleData: merkleDataResp
|
|
66
79
|
});
|
|
@@ -118,7 +131,7 @@ class GearboxRewardsApi {
|
|
|
118
131
|
contracts: [...farmInfoCalls, ...rewardTokenCalls, ...farmedCalls]
|
|
119
132
|
})
|
|
120
133
|
]);
|
|
121
|
-
const safeResponse =
|
|
134
|
+
const safeResponse = GearboxRewardsApi.extractFulfilled(response, reportError, "v3Rewards") || [];
|
|
122
135
|
const farmInfoCallsEnd = farmInfoCalls.length;
|
|
123
136
|
const farmInfo = safeResponse.slice(
|
|
124
137
|
0,
|
|
@@ -181,7 +194,7 @@ class GearboxRewardsApi {
|
|
|
181
194
|
})
|
|
182
195
|
)
|
|
183
196
|
]);
|
|
184
|
-
const merkleXYZLm =
|
|
197
|
+
const merkleXYZLm = GearboxRewardsApi.extractFulfilled(
|
|
185
198
|
merkleXYZLMResponse,
|
|
186
199
|
reportError,
|
|
187
200
|
"merkleXYZLm"
|
|
@@ -245,7 +258,7 @@ class GearboxRewardsApi {
|
|
|
245
258
|
}) {
|
|
246
259
|
if (!airdropDistributorAddress)
|
|
247
260
|
throw new Error(`V2 rewards are not supported on chain: ${network}`);
|
|
248
|
-
const merkleData = await
|
|
261
|
+
const merkleData = await GearboxRewardsApi.getMerkle(
|
|
249
262
|
provider,
|
|
250
263
|
airdropDistributorAddress,
|
|
251
264
|
network,
|
|
@@ -38,7 +38,7 @@ class GearboxRewardsApy {
|
|
|
38
38
|
const info = rewardPoolsInfo[stakedDieselToken];
|
|
39
39
|
if (!info) return [];
|
|
40
40
|
const extra = (Array.isArray(info) ? info : [info]).map(
|
|
41
|
-
(inf) =>
|
|
41
|
+
(inf) => GearboxRewardsApy.getPoolSingleExtraLmAPY_V3({
|
|
42
42
|
...restProps,
|
|
43
43
|
stakedDieselToken,
|
|
44
44
|
rewardPoolsInfo: inf
|
|
@@ -64,7 +64,7 @@ class GearboxRewardsApy {
|
|
|
64
64
|
const rewardAddress = currentTokenData[rewardPoolsInfo.symbol];
|
|
65
65
|
const { decimals: rewardDecimals = 18 } = tokensList[rewardAddress] || {};
|
|
66
66
|
const rewardPrice = prices[rewardAddress] ?? 0n;
|
|
67
|
-
const r =
|
|
67
|
+
const r = GearboxRewardsApy.calculateAPY_V3({
|
|
68
68
|
currentTimestamp,
|
|
69
69
|
info: rewardPoolsInfo,
|
|
70
70
|
supply: {
|
|
@@ -115,20 +115,23 @@ class GearboxRewardsApy {
|
|
|
115
115
|
assets,
|
|
116
116
|
...restProps
|
|
117
117
|
}) {
|
|
118
|
-
const extra = assets.reduce(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
118
|
+
const extra = assets.reduce(
|
|
119
|
+
(acc, asset) => {
|
|
120
|
+
const { token } = asset;
|
|
121
|
+
const info = rewardInfo[token || ""];
|
|
122
|
+
if (!info || info.length === 0) return acc;
|
|
123
|
+
const extra2 = info.map(
|
|
124
|
+
(inf) => GearboxRewardsApy.getCASingleExtraAPY_V3({
|
|
125
|
+
...restProps,
|
|
126
|
+
asset,
|
|
127
|
+
rewardInfo: inf
|
|
128
|
+
})
|
|
129
|
+
);
|
|
130
|
+
acc.push(...extra2);
|
|
131
|
+
return acc;
|
|
132
|
+
},
|
|
133
|
+
[]
|
|
134
|
+
);
|
|
132
135
|
return extra;
|
|
133
136
|
}
|
|
134
137
|
static getCASingleExtraAPY_V3({
|
|
@@ -147,7 +150,7 @@ class GearboxRewardsApy {
|
|
|
147
150
|
const rewardAddress = currentTokenData[rewardInfo.symbol];
|
|
148
151
|
const { decimals: rewardDecimals = 18 } = tokensList[rewardAddress] || {};
|
|
149
152
|
const rewardPrice = prices[rewardAddress] ?? 0n;
|
|
150
|
-
const r =
|
|
153
|
+
const r = GearboxRewardsApy.calculateAPY_V3({
|
|
151
154
|
currentTimestamp,
|
|
152
155
|
info: rewardInfo,
|
|
153
156
|
supply: {
|
|
@@ -45,7 +45,9 @@ class GearboxRewardsExtraApy {
|
|
|
45
45
|
}) {
|
|
46
46
|
const list = [...new Set(tokensToCheck)];
|
|
47
47
|
const res = await Promise.allSettled(
|
|
48
|
-
list.map(
|
|
48
|
+
list.map(
|
|
49
|
+
(t) => GearboxRewardsExtraApy.getTokenTotal(t, network, tokensList)
|
|
50
|
+
)
|
|
49
51
|
);
|
|
50
52
|
return res.map((r, i) => [
|
|
51
53
|
list[i],
|
|
@@ -79,7 +81,7 @@ class GearboxRewardsExtraApy {
|
|
|
79
81
|
(acc2, pointsInfo2) => {
|
|
80
82
|
const { address: tokenAddress } = tokensList[pointsInfo2.token];
|
|
81
83
|
const tokenBalance = totalTokenBalances[tokenAddress || ""];
|
|
82
|
-
const points =
|
|
84
|
+
const points = GearboxRewardsExtraApy.getPoolTokenPoints(
|
|
83
85
|
tokenBalance,
|
|
84
86
|
p,
|
|
85
87
|
tokensList,
|
|
@@ -42,7 +42,7 @@ function createRawTx(to, parameters, description) {
|
|
|
42
42
|
if (inputs.length > 0 && args && args.length !== 0) {
|
|
43
43
|
args.forEach((arg, i) => {
|
|
44
44
|
const methodName = inputs[i].name;
|
|
45
|
-
|
|
45
|
+
const stringifiedArg = arg instanceof BigInt ? arg.toString() : arg;
|
|
46
46
|
contractInputsValues[methodName] = Array.isArray(stringifiedArg) ? (0, import_json.json_stringify)(stringifiedArg) : stringifiedArg;
|
|
47
47
|
});
|
|
48
48
|
}
|
|
@@ -35,9 +35,9 @@ const toBigInt = (v) => {
|
|
|
35
35
|
const value = typeof v === "object" && v.type === "BigNumber" ? v.hex : v.toString();
|
|
36
36
|
return BigInt(value);
|
|
37
37
|
};
|
|
38
|
-
const percentFmt = (v, raw = true) => `${(Number(v) / 100).toFixed(2)}
|
|
38
|
+
const percentFmt = (v, raw = true) => `${(Number(v) / 100).toFixed(2)}%${raw ? ` [${v}]` : ""}`;
|
|
39
39
|
function formatBNvalue(num, decimals, precision, raw = true) {
|
|
40
|
-
return `${formatBN(num, decimals, precision)}
|
|
40
|
+
return `${formatBN(num, decimals, precision)}${raw ? ` [ ${num} ]` : ""}`;
|
|
41
41
|
}
|
|
42
42
|
function formatBN(num, decimals, precision) {
|
|
43
43
|
if (num === void 0) {
|
|
@@ -71,7 +71,7 @@ const limitPrecision = (n, p) => {
|
|
|
71
71
|
return p;
|
|
72
72
|
};
|
|
73
73
|
const limitNum = (n, d = 18) => {
|
|
74
|
-
|
|
74
|
+
const limited = n <= 2n ? 0n : n;
|
|
75
75
|
if (d <= 6) {
|
|
76
76
|
return limited * 10n ** BigInt(6 - d);
|
|
77
77
|
} else {
|
|
@@ -115,7 +115,7 @@ function formatDuration(seconds, raw = true) {
|
|
|
115
115
|
const start = new Date(now);
|
|
116
116
|
const end = new Date(now + seconds * 1e3);
|
|
117
117
|
const duration = (0, import_date_fns.intervalToDuration)({ start, end });
|
|
118
|
-
return `${(0, import_date_fns.formatDuration)(duration)}
|
|
118
|
+
return `${(0, import_date_fns.formatDuration)(duration)}${raw ? `[${seconds.toString()}]` : ""}`;
|
|
119
119
|
}
|
|
120
120
|
function formatNumberToString_(value) {
|
|
121
121
|
return value.toLocaleString("en-US", { minimumIntegerDigits: 1, useGrouping: true }).replaceAll(",", "_");
|
|
@@ -183,7 +183,7 @@ function extractCallError(result) {
|
|
|
183
183
|
const err = result.error;
|
|
184
184
|
const error = err instanceof import_viem.BaseError ? err.walk((e) => e instanceof import_viem.ContractFunctionRevertedError) : void 0;
|
|
185
185
|
if (error instanceof import_viem.ContractFunctionRevertedError) {
|
|
186
|
-
return
|
|
186
|
+
return `[${error.data?.errorName ?? "reverted"}]`;
|
|
187
187
|
}
|
|
188
188
|
if (err instanceof import_viem.CallExecutionError) {
|
|
189
189
|
return `[${err.name}: ${err.details}]`;
|
|
@@ -198,7 +198,7 @@ class SimulateWithPriceUpdatesError extends import_viem.BaseError {
|
|
|
198
198
|
const { calls, priceUpdates, timestamp, request } = params;
|
|
199
199
|
const blockNumber = request?.blockNumber ?? 0n;
|
|
200
200
|
const base = cause instanceof import_viem.BaseError ? cause : {};
|
|
201
|
-
|
|
201
|
+
const causeMeta = base.metaMessages ? [...base.metaMessages, " "] : [];
|
|
202
202
|
super(
|
|
203
203
|
`simulate multicall with ${priceUpdates.length} price updates failed`,
|
|
204
204
|
{
|
|
@@ -38,7 +38,7 @@ class AccountOpener extends SDKConstruct {
|
|
|
38
38
|
});
|
|
39
39
|
try {
|
|
40
40
|
this.#faucet = options.faucet ?? service.sdk.addressProvider.getAddress("FAUCET");
|
|
41
|
-
} catch (
|
|
41
|
+
} catch (_e) {
|
|
42
42
|
this.#logger?.warn("faucet not found, will not claim from faucet");
|
|
43
43
|
}
|
|
44
44
|
this.#borrower = options.borrower;
|
|
@@ -260,7 +260,7 @@ class AccountOpener extends SDKConstruct {
|
|
|
260
260
|
minAvailableByPool[cm.pool] = (minAvailableByPool[cm.pool] ?? 0n) + minDebt * (leverage - PERCENTAGE_FACTOR) / PERCENTAGE_FACTOR * this.#poolDepositMultiplier / PERCENTAGE_FACTOR;
|
|
261
261
|
}
|
|
262
262
|
let totalUSD = 0n;
|
|
263
|
-
|
|
263
|
+
const deposits = [];
|
|
264
264
|
for (const [p, minAvailable] of Object.entries(minAvailableByPool)) {
|
|
265
265
|
const market = this.sdk.marketRegister.findByPool(p);
|
|
266
266
|
const pool = market.pool.pool;
|
|
@@ -348,7 +348,7 @@ class AccountOpener extends SDKConstruct {
|
|
|
348
348
|
async #prepareBorrower(targets) {
|
|
349
349
|
const borrower = await this.#getBorrower();
|
|
350
350
|
let claimUSD = 0n;
|
|
351
|
-
|
|
351
|
+
const degenNFTS = {};
|
|
352
352
|
for (const target of targets) {
|
|
353
353
|
const cm = this.sdk.marketRegister.findCreditManager(
|
|
354
354
|
target.creditManager
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iBalancerV2VaultAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iBalancerV2VaultAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iBalancerV2VaultAdapterAbi;
|
|
4
4
|
class BalancerV2VaultAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iBalancerV3RouterAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iBalancerV3RouterAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iBalancerV3RouterAdapterAbi;
|
|
4
4
|
class BalancerV3RouterAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCamelotV3AdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iCamelotV3AdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iCamelotV3AdapterAbi;
|
|
4
4
|
class CamelotV3AdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iConvexV1BaseRewardPoolAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iConvexV1BaseRewardPoolAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iConvexV1BaseRewardPoolAdapterAbi;
|
|
4
4
|
class ConvexV1BaseRewardPoolAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iConvexV1BoosterAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iConvexV1BoosterAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iConvexV1BoosterAdapterAbi;
|
|
4
4
|
class ConvexV1BoosterAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCurveV1_2AssetsAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iCurveV1_2AssetsAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iCurveV1_2AssetsAdapterAbi;
|
|
4
4
|
class Curve2AssetsAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCurveV1_3AssetsAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iCurveV1_3AssetsAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iCurveV1_3AssetsAdapterAbi;
|
|
4
4
|
class Curve3AssetsAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCurveV1_4AssetsAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iCurveV1_4AssetsAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iCurveV1_4AssetsAdapterAbi;
|
|
4
4
|
class Curve4AssetsAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCurveV1AdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iCurveV1AdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iCurveV1AdapterAbi;
|
|
4
4
|
class CurveV1AdapterDeposit extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCurveV1_2AssetsAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iCurveV1_2AssetsAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iCurveV1_2AssetsAdapterAbi;
|
|
4
4
|
class CurveV1AdapterStETHContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCurveV1StableNgAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iCurveV1StableNgAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iCurveV1StableNgAdapterAbi;
|
|
4
4
|
class CurveV1StableNGAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iDaiUsdsAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iDaiUsdsAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iDaiUsdsAdapterAbi;
|
|
4
4
|
class DaiUsdsAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ierc4626AdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { ierc4626AdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = ierc4626AdapterAbi;
|
|
4
4
|
class ERC4626AdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iEqualizerRouterAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iEqualizerRouterAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iEqualizerRouterAdapterAbi;
|
|
4
4
|
class EqualizerRouterAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ierc4626AdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { ierc4626AdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = ierc4626AdapterAbi;
|
|
4
4
|
class MellowERC4626VaultAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iMellowVaultAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iMellowVaultAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iMellowVaultAdapterAbi;
|
|
4
4
|
class MellowVaultAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iPendleRouterAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iPendleRouterAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iPendleRouterAdapterAbi;
|
|
4
4
|
class PendleRouterAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iStakingRewardsAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iStakingRewardsAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iStakingRewardsAdapterAbi;
|
|
4
4
|
class StakingRewardsAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { formatBN } from "../../sdk/index.js";
|
|
2
|
-
import { iUniswapV2AdapterAbi } from "./abi/index.js";
|
|
3
2
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
3
|
+
import { iUniswapV2AdapterAbi } from "./abi/index.js";
|
|
4
4
|
const abi = iUniswapV2AdapterAbi;
|
|
5
5
|
class UniswapV2AdapterContract extends AbstractAdapterContract {
|
|
6
6
|
constructor(sdk, args) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { formatBN } from "../../sdk/index.js";
|
|
2
|
-
import { iUniswapV3AdapterAbi } from "./abi/index.js";
|
|
3
2
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
3
|
+
import { iUniswapV3AdapterAbi } from "./abi/index.js";
|
|
4
4
|
const abi = iUniswapV3AdapterAbi;
|
|
5
5
|
class UniswapV3AdapterContract extends AbstractAdapterContract {
|
|
6
6
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iVelodromeV2RouterAdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iVelodromeV2RouterAdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iVelodromeV2RouterAdapterAbi;
|
|
4
4
|
class VelodromeV2RouterAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iwstEthv1AdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iwstEthv1AdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iwstEthv1AdapterAbi;
|
|
4
4
|
class WstETHV1AdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iYearnV2AdapterAbi } from "./abi/index.js";
|
|
2
1
|
import { AbstractAdapterContract } from "./AbstractAdapter.js";
|
|
2
|
+
import { iYearnV2AdapterAbi } from "./abi/index.js";
|
|
3
3
|
const abi = iYearnV2AdapterAbi;
|
|
4
4
|
class YearnV2RouterAdapterContract extends AbstractAdapterContract {
|
|
5
5
|
constructor(sdk, args) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export * from "./abi/index.js";
|
|
2
1
|
export * from "./AbstractAdapter.js";
|
|
3
2
|
export * from "./AdaptersPlugin.js";
|
|
3
|
+
export * from "./abi/index.js";
|
|
4
4
|
export * from "./BalancerV2VaultAdapterContract.js";
|
|
5
5
|
export * from "./BalancerV3RouterAdapterContract.js";
|
|
6
6
|
export * from "./CamelotV3AdapterContract.js";
|
|
@@ -31,7 +31,7 @@ class DegenDistributorsPlugin extends BasePlugin {
|
|
|
31
31
|
const cfgLC = cfg.toLowerCase();
|
|
32
32
|
const r = distributorByConfigurator?.[cfgLC];
|
|
33
33
|
if (r.status === "fulfilled") {
|
|
34
|
-
this.#distributors
|
|
34
|
+
this.#distributors?.upsert(pool, r.value);
|
|
35
35
|
} else {
|
|
36
36
|
this.sdk.logger?.error(
|
|
37
37
|
`failed to load degen distributor for market configurator ${this.labelAddress(cfg)} and pool ${this.labelAddress(pool)}: ${r.reason}`
|
|
@@ -41,7 +41,7 @@ class Pools7DAgoPlugin extends BasePlugin {
|
|
|
41
41
|
const cfg = m.configurator.address;
|
|
42
42
|
const pool = m.pool.pool.address;
|
|
43
43
|
if (r.status === "success") {
|
|
44
|
-
this.#pools7DAgo
|
|
44
|
+
this.#pools7DAgo?.upsert(m.pool.pool.address, {
|
|
45
45
|
dieselRate: r.result.dieselRate,
|
|
46
46
|
pool
|
|
47
47
|
});
|