@1delta/margin-fetcher 0.0.215 → 0.0.216

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/index.js CHANGED
@@ -17893,7 +17893,7 @@ var getEulerV2ReservesDataConverter = (lender, chainId, prices, additionalYields
17893
17893
  };
17894
17894
 
17895
17895
  // src/lending/public-data/aave-v4-type/publicCallBuild.ts
17896
- var CALLS_PER_RESERVE = 6;
17896
+ var BASE_CALLS_PER_RESERVE = 5;
17897
17897
  var CALLS_PER_SPOKE_TAIL = 2;
17898
17898
  function isValidAddress(addr) {
17899
17899
  return !!addr && addr !== "0x" && addr.length > 2;
@@ -17901,6 +17901,10 @@ function isValidAddress(addr) {
17901
17901
  function getSpokeReserves(reservesMap, spokeAddr) {
17902
17902
  return reservesMap[spokeAddr.toLowerCase()] ?? reservesMap[spokeAddr] ?? [];
17903
17903
  }
17904
+ function getDynamicConfigCount(spokeEntry) {
17905
+ const max = spokeEntry.dynamicConfigKeyMax ?? 0;
17906
+ return max + 1;
17907
+ }
17904
17908
  var buildAaveV4LenderReserveCall = (chainId, lender) => {
17905
17909
  const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
17906
17910
  const reservesMap = aaveV4Reserves()?.[lender]?.[chainId] ?? {};
@@ -17912,6 +17916,7 @@ var buildAaveV4LenderReserveCall = (chainId, lender) => {
17912
17916
  if (!isValidAddress(spokeEntry.spoke)) continue;
17913
17917
  const spokeAddr = spokeEntry.spoke;
17914
17918
  const reserves = getSpokeReserves(reservesMap, spokeAddr);
17919
+ const dynConfigCount = getDynamicConfigCount(spokeEntry);
17915
17920
  for (const entry of reserves) {
17916
17921
  const rid = typeof entry === "number" ? entry : entry.reserveId;
17917
17922
  calls.push(
@@ -17939,13 +17944,15 @@ var buildAaveV4LenderReserveCall = (chainId, lender) => {
17939
17944
  address: spokeAddr,
17940
17945
  name: "getReserveTotalDebt",
17941
17946
  params: [rid]
17942
- },
17943
- {
17944
- address: spokeAddr,
17945
- name: "getDynamicReserveConfig",
17946
- params: [rid, 0]
17947
17947
  }
17948
17948
  );
17949
+ for (let key = 0; key < dynConfigCount; key++) {
17950
+ calls.push({
17951
+ address: spokeAddr,
17952
+ name: "getDynamicReserveConfig",
17953
+ params: [rid, key]
17954
+ });
17955
+ }
17949
17956
  if (typeof entry === "object" && spokeEntry.hub && entry.assetId !== void 0) {
17950
17957
  const hubLc = spokeEntry.hub.toLowerCase();
17951
17958
  const key = `${hubLc}:${entry.assetId}`;
@@ -18020,7 +18027,8 @@ var getAaveV4ExpectedCallCount = (chainId, lender) => {
18020
18027
  reservesMap,
18021
18028
  spokeEntry.spoke
18022
18029
  );
18023
- count += reserves.length * CALLS_PER_RESERVE + CALLS_PER_SPOKE_TAIL;
18030
+ const dynConfigCount = getDynamicConfigCount(spokeEntry);
18031
+ count += reserves.length * (BASE_CALLS_PER_RESERVE + dynConfigCount) + CALLS_PER_SPOKE_TAIL;
18024
18032
  const rids = reserves.map(
18025
18033
  (e) => typeof e === "number" ? e : e.reserveId
18026
18034
  );
@@ -18029,7 +18037,9 @@ var getAaveV4ExpectedCallCount = (chainId, lender) => {
18029
18037
  }
18030
18038
  for (const entry of reserves) {
18031
18039
  if (typeof entry === "object" && spokeEntry.hub && entry.assetId !== void 0) {
18032
- hubAssetKeys.add(`${spokeEntry.hub.toLowerCase()}:${entry.assetId}`);
18040
+ hubAssetKeys.add(
18041
+ `${spokeEntry.hub.toLowerCase()}:${entry.assetId}`
18042
+ );
18033
18043
  }
18034
18044
  }
18035
18045
  }
@@ -18208,18 +18218,35 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18208
18218
  if (!isValidAddress2(spokeEntry.spoke)) continue;
18209
18219
  const spokeAddr = spokeEntry.spoke;
18210
18220
  const reserves = getSpokeReserves2(reservesMap, spokeAddr);
18211
- const reserveCount = reserves.length;
18221
+ const dynConfigCount = (spokeEntry.dynamicConfigKeyMax ?? 0) + 1;
18212
18222
  const parsedReserves = [];
18213
- for (let i = 0; i < reserveCount; i++) {
18223
+ for (let i = 0; i < reserves.length; i++) {
18214
18224
  const entry = reserves[i];
18215
18225
  const reserveId = typeof entry === "number" ? entry : entry.reserveId;
18216
- const baseIdx = offset + i * CALLS_PER_RESERVE;
18217
- const rawReserve = data[baseIdx];
18218
- const rawConfig = data[baseIdx + 1];
18219
- const rawSupplied = data[baseIdx + 2];
18220
- const rawDebt = data[baseIdx + 3];
18221
- const rawTotalDebt = data[baseIdx + 4];
18222
- const rawDynConfig = data[baseIdx + 5];
18226
+ const rawReserve = data[offset];
18227
+ const rawConfig = data[offset + 1];
18228
+ const rawSupplied = data[offset + 2];
18229
+ const rawDebt = data[offset + 3];
18230
+ const rawTotalDebt = data[offset + 4];
18231
+ offset += BASE_CALLS_PER_RESERVE;
18232
+ const dynamicConfigs = {};
18233
+ for (let key = 0; key < dynConfigCount; key++) {
18234
+ const rawDynConfig = data[offset];
18235
+ offset += 1;
18236
+ if (rawDynConfig && rawDynConfig !== "0x") {
18237
+ dynamicConfigs[key] = {
18238
+ collateralFactor: Number(
18239
+ rawDynConfig?.collateralFactor ?? 0
18240
+ ),
18241
+ maxLiquidationBonus: Number(
18242
+ rawDynConfig?.maxLiquidationBonus ?? 0
18243
+ ),
18244
+ liquidationFee: Number(
18245
+ rawDynConfig?.liquidationFee ?? 0
18246
+ )
18247
+ };
18248
+ }
18249
+ }
18223
18250
  const reserve = {
18224
18251
  underlying: rawReserve?.underlying ?? "",
18225
18252
  hub: rawReserve?.hub ?? "",
@@ -18248,20 +18275,6 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18248
18275
  } else {
18249
18276
  drawnDebt = BigInt(rawDebt ?? 0);
18250
18277
  }
18251
- const dynamicConfigs = {};
18252
- if (rawDynConfig && rawDynConfig !== "0x") {
18253
- dynamicConfigs[0] = {
18254
- collateralFactor: Number(
18255
- rawDynConfig?.collateralFactor ?? 0
18256
- ),
18257
- maxLiquidationBonus: Number(
18258
- rawDynConfig?.maxLiquidationBonus ?? 0
18259
- ),
18260
- liquidationFee: Number(
18261
- rawDynConfig?.liquidationFee ?? 0
18262
- )
18263
- };
18264
- }
18265
18278
  if (spokeEntry.hub && typeof entry === "object" && entry.assetId !== void 0) {
18266
18279
  const hubLc = spokeEntry.hub.toLowerCase();
18267
18280
  const key = `${hubLc}:${entry.assetId}`;
@@ -18286,7 +18299,6 @@ var getAaveV4ReservesDataConverter = (lender, chainId, prices, additionalYields,
18286
18299
  price: 0n
18287
18300
  });
18288
18301
  }
18289
- offset += reserveCount * CALLS_PER_RESERVE;
18290
18302
  const rawLiqConfig = data[offset];
18291
18303
  const rawOracle = data[offset + 1];
18292
18304
  offset += CALLS_PER_SPOKE_TAIL;
@@ -19042,7 +19054,7 @@ var buildEulerUserCall = async (chainId, lender, account, subAccountIndexes) =>
19042
19054
  };
19043
19055
 
19044
19056
  // src/lending/user-data/aave-v4-type/userCallBuild.ts
19045
- var USER_CALLS_PER_RESERVE = 3;
19057
+ var USER_CALLS_PER_RESERVE = 4;
19046
19058
  var buildAaveV4UserCall = (chainId, lender, account) => {
19047
19059
  const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
19048
19060
  const reservesMap = aaveV4Reserves()?.[lender]?.[chainId] ?? {};
@@ -19069,6 +19081,11 @@ var buildAaveV4UserCall = (chainId, lender, account) => {
19069
19081
  address: spokeAddr,
19070
19082
  name: "getUserReserveStatus",
19071
19083
  params: [rid, account]
19084
+ },
19085
+ {
19086
+ address: spokeAddr,
19087
+ name: "getUserPosition",
19088
+ params: [rid, account]
19072
19089
  }
19073
19090
  );
19074
19091
  }
@@ -20237,21 +20254,230 @@ var getEulerUserDataConverter = (lender, chainId, account, metaMap, subAccountIn
20237
20254
  ];
20238
20255
  };
20239
20256
 
20257
+ // src/lending/user-data/aave-v4-type/createAaveV4UserState.ts
20258
+ function resolveV4Config(configs, userConfigKey) {
20259
+ if (!configs) return { config: void 0, spokeAddr: void 0 };
20260
+ if (userConfigKey && configs[userConfigKey]) {
20261
+ return {
20262
+ config: configs[userConfigKey],
20263
+ spokeAddr: userConfigKey.split(":")[0]
20264
+ };
20265
+ }
20266
+ const entries = Object.entries(configs);
20267
+ if (entries.length === 0) return { config: void 0, spokeAddr: void 0 };
20268
+ const [key, config] = entries[0];
20269
+ const spokeAddr = key.split(":")[0];
20270
+ return { config, spokeAddr };
20271
+ }
20272
+ function getConfigScopedPrice(meta, spokeAddr, configPriceMap) {
20273
+ return getOraclePrice(meta);
20274
+ }
20275
+ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalDebt24h = 0, configPriceMap) {
20276
+ const assetKeys = getMarketUidsFromMeta(lenderData);
20277
+ const { chainId, account } = payload;
20278
+ let depositInterest = 0;
20279
+ let borrowInterest = 0;
20280
+ let rewardDepositAccrual = 0;
20281
+ let rewardBorrowAccrual = 0;
20282
+ let stakingDepositAccrual = 0;
20283
+ let stakingBorrowAccrual = 0;
20284
+ let deposits = 0;
20285
+ let debt = 0;
20286
+ let oracleDebt = 0;
20287
+ let collateral = 0;
20288
+ let borrowDiscountedCollateral = 0;
20289
+ let borrowDiscountedCollateralAllActive = 0;
20290
+ let collateralAllActive = 0;
20291
+ let rewardsPerAsset = {};
20292
+ for (const marketUid of assetKeys) {
20293
+ if (!lenderData?.[marketUid] || !payload.lendingPositions[marketUid])
20294
+ continue;
20295
+ const pos = payload.lendingPositions[marketUid];
20296
+ const { depositsUSD, debtStableUSD, debtUSD, collateralEnabled } = pos;
20297
+ const depositsUSDOracle = pos.depositsUSDOracle ?? depositsUSD;
20298
+ const debtUSDOracle = pos.debtUSDOracle ?? debtUSD;
20299
+ const {
20300
+ depositRate,
20301
+ intrinsicYield,
20302
+ variableBorrowRate,
20303
+ stableBorrowRate,
20304
+ rewards,
20305
+ flags,
20306
+ configs
20307
+ } = lenderData[marketUid];
20308
+ const { config: userConfigForAsset } = resolveV4Config(
20309
+ configs,
20310
+ pos.userConfigKey
20311
+ );
20312
+ deposits += depositsUSD;
20313
+ debt += debtUSD + (debtStableUSD ?? 0);
20314
+ oracleDebt += debtUSDOracle + (pos.debtStableUSDOracle ?? debtStableUSD ?? 0);
20315
+ (rewards ?? []).forEach((rewardData) => {
20316
+ const key = rewardData.asset;
20317
+ rewardDepositAccrual += rewardData.depositRate * depositsUSD;
20318
+ rewardBorrowAccrual += rewardData.variableBorrowRate * debtUSD;
20319
+ const rewDepo = rewardData.depositRate * depositsUSD;
20320
+ const rewDebt = rewardData.variableBorrowRate * debtUSD;
20321
+ if (!rewardsPerAsset[key])
20322
+ rewardsPerAsset[key] = { depositApr: 0, borrowApr: 0 };
20323
+ if (rewDepo > 0) rewardsPerAsset[key].depositApr += rewDepo;
20324
+ if (rewDebt > 0) rewardsPerAsset[key].borrowApr += rewDebt;
20325
+ });
20326
+ stakingDepositAccrual += (intrinsicYield ?? 0) * depositsUSD;
20327
+ stakingBorrowAccrual += (intrinsicYield ?? 0) * debtUSD;
20328
+ if (flags?.collateralActive || userConfigForAsset && !userConfigForAsset.collateralDisabled) {
20329
+ if (collateralEnabled) {
20330
+ collateral += (userConfigForAsset?.collateralFactor ?? 1) * depositsUSDOracle;
20331
+ borrowDiscountedCollateral += (userConfigForAsset?.borrowCollateralFactor ?? 1) * depositsUSDOracle;
20332
+ }
20333
+ borrowDiscountedCollateralAllActive += (userConfigForAsset?.borrowCollateralFactor ?? 1) * depositsUSDOracle;
20334
+ collateralAllActive += (userConfigForAsset?.collateralFactor ?? 1) * depositsUSDOracle;
20335
+ }
20336
+ depositInterest += (depositRate ?? 0) * depositsUSD;
20337
+ borrowInterest += debtUSD * (variableBorrowRate ?? 0) + (debtStableUSD ?? 0) * (stableBorrowRate ?? 0);
20338
+ }
20339
+ const nav = deposits - debt;
20340
+ const balanceData2 = {
20341
+ borrowDiscountedCollateral,
20342
+ borrowDiscountedCollateralAllActive,
20343
+ collateral,
20344
+ collateralAllActive,
20345
+ deposits,
20346
+ debt,
20347
+ adjustedDebt: oracleDebt,
20348
+ nav,
20349
+ deposits24h: totalDeposits24h,
20350
+ debt24h: totalDebt24h,
20351
+ nav24h: totalDeposits24h - totalDebt24h,
20352
+ ...payload.rewards ? { rewards: payload.rewards } : {}
20353
+ };
20354
+ const aprData2 = {
20355
+ apr: safeDivide(depositInterest - borrowInterest, nav),
20356
+ borrowApr: safeDivide(borrowInterest, debt),
20357
+ depositApr: safeDivide(depositInterest, deposits),
20358
+ rewards: divideAccrualsToAprs(rewardsPerAsset, nav, deposits, debt),
20359
+ rewardApr: safeDivide(rewardDepositAccrual + rewardBorrowAccrual, nav),
20360
+ rewardDepositApr: safeDivide(rewardDepositAccrual, deposits),
20361
+ rewardBorrowApr: safeDivide(rewardBorrowAccrual, debt),
20362
+ intrinsicApr: safeDivide(stakingDepositAccrual - stakingBorrowAccrual, nav),
20363
+ intrinsicDepositApr: safeDivide(stakingDepositAccrual, deposits),
20364
+ intrinsicBorrowApr: safeDivide(stakingBorrowAccrual, debt)
20365
+ };
20366
+ const userConfig = {
20367
+ selectedMode: "0",
20368
+ id: account,
20369
+ isWhitelisted: true
20370
+ };
20371
+ const creditLine = Math.max(
20372
+ 0,
20373
+ borrowDiscountedCollateral - balanceData2.adjustedDebt
20374
+ );
20375
+ for (const marketUid of assetKeys) {
20376
+ if (!lenderData?.[marketUid]) continue;
20377
+ const meta = lenderData[marketUid];
20378
+ const { configs, flags, borrowLiquidity, withdrawLiquidity } = meta;
20379
+ const pos = payload.lendingPositions[marketUid];
20380
+ const { config, spokeAddr } = resolveV4Config(
20381
+ configs,
20382
+ pos ? pos.userConfigKey : void 0
20383
+ );
20384
+ const price = getConfigScopedPrice(meta);
20385
+ const bcf = config?.borrowCollateralFactor ?? 1;
20386
+ const bf = config?.borrowFactor ?? 1;
20387
+ if (pos) {
20388
+ let withdrawable;
20389
+ if (!pos.collateralEnabled || config?.collateralDisabled) {
20390
+ withdrawable = String(pos.deposits);
20391
+ } else if (balanceData2.debt === 0) {
20392
+ withdrawable = String(pos.deposits);
20393
+ } else {
20394
+ const withdrawableUSD = Math.max(creditLine / bcf, 0);
20395
+ withdrawable = String(
20396
+ Math.min(withdrawableUSD / price, Number(pos.deposits))
20397
+ );
20398
+ }
20399
+ if (withdrawLiquidity != null) {
20400
+ withdrawable = String(Math.min(Number(withdrawable), withdrawLiquidity));
20401
+ }
20402
+ let borrowable;
20403
+ if (!flags?.borrowingEnabled || flags?.isFrozen || config?.debtDisabled) {
20404
+ borrowable = "0";
20405
+ } else {
20406
+ const borrowableUSD = Math.max(creditLine / bf, 0);
20407
+ borrowable = String(borrowableUSD / price);
20408
+ }
20409
+ if (borrowLiquidity != null) {
20410
+ borrowable = String(Math.min(Number(borrowable), borrowLiquidity));
20411
+ }
20412
+ pos.withdrawable = withdrawable;
20413
+ pos.borrowable = borrowable;
20414
+ pos.underlyingInfo = buildUnderlyingInfo(meta);
20415
+ } else if ((deposits > 0 || debt > 0) && flags?.borrowingEnabled && !flags?.isFrozen && !config?.debtDisabled) {
20416
+ let borrowable = String(Math.max(creditLine / bf, 0) / price);
20417
+ if (borrowLiquidity != null) {
20418
+ borrowable = String(Math.min(Number(borrowable), borrowLiquidity));
20419
+ }
20420
+ payload.lendingPositions[marketUid] = {
20421
+ marketUid,
20422
+ deposits: "0",
20423
+ debt: "0",
20424
+ debtStable: "0",
20425
+ depositsUSD: 0,
20426
+ debtUSD: 0,
20427
+ debtStableUSD: 0,
20428
+ collateralEnabled: false,
20429
+ claimableRewards: 0,
20430
+ withdrawable: "0",
20431
+ borrowable,
20432
+ underlyingInfo: buildUnderlyingInfo(meta)
20433
+ };
20434
+ }
20435
+ }
20436
+ return {
20437
+ lender: "",
20438
+ account,
20439
+ chainId,
20440
+ data: [
20441
+ {
20442
+ health: balanceData2.debt === 0 ? null : balanceData2.adjustedDebt > 0 ? balanceData2.collateral / balanceData2.adjustedDebt : balanceData2.collateral / balanceData2.debt,
20443
+ borrowCapacityUSD: creditLine,
20444
+ accountId: "0",
20445
+ balanceData: balanceData2,
20446
+ aprData: aprData2,
20447
+ userConfig,
20448
+ positions: Object.values(payload.lendingPositions)
20449
+ }
20450
+ ]
20451
+ };
20452
+ }
20453
+
20240
20454
  // src/lending/user-data/aave-v4-type/userCallParse.ts
20241
20455
  var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20242
20456
  const spokes = aaveV4Spokes()?.[lender]?.[chainId] ?? [];
20243
20457
  const reservesMap = aaveV4Reserves()?.[lender]?.[chainId] ?? {};
20458
+ const oracleEntries = aaveV4Oracles()?.[lender]?.[chainId] ?? [];
20459
+ const spokeReserveToUnderlying = /* @__PURE__ */ new Map();
20460
+ for (const oe of oracleEntries) {
20461
+ if (oe.underlying && oe.spoke) {
20462
+ spokeReserveToUnderlying.set(
20463
+ `${oe.spoke.toLowerCase()}:${oe.reserveId}`,
20464
+ oe.underlying.toLowerCase()
20465
+ );
20466
+ }
20467
+ }
20244
20468
  const reserveEntries = [];
20245
20469
  for (const spokeEntry of spokes) {
20246
20470
  const spokeAddr = spokeEntry.spoke;
20247
20471
  if (!spokeAddr || spokeAddr === "0x" || spokeAddr.length <= 2) continue;
20248
20472
  const reserves = reservesMap[spokeAddr.toLowerCase()] ?? reservesMap[spokeAddr] ?? [];
20249
20473
  for (const entry of reserves) {
20474
+ const rid = typeof entry === "number" ? entry : entry.reserveId;
20475
+ const underlying = ((typeof entry === "object" ? entry.underlying : void 0) ?? spokeReserveToUnderlying.get(`${spokeAddr.toLowerCase()}:${rid}`) ?? "").toLowerCase();
20250
20476
  reserveEntries.push({
20251
20477
  spokeAddr,
20252
- reserveId: typeof entry === "number" ? entry : entry.reserveId,
20478
+ reserveId: rid,
20253
20479
  hub: (spokeEntry.hub ?? "").toLowerCase(),
20254
- underlying: (typeof entry === "object" ? entry.underlying ?? "" : "").toLowerCase()
20480
+ underlying
20255
20481
  });
20256
20482
  }
20257
20483
  }
@@ -20262,12 +20488,23 @@ var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20262
20488
  return void 0;
20263
20489
  }
20264
20490
  const lendingPositions = {};
20491
+ const underlyingToUid = /* @__PURE__ */ new Map();
20492
+ if (metaMap) {
20493
+ for (const [uid, meta] of Object.entries(metaMap)) {
20494
+ const addr = (meta?.underlying ?? "").toLowerCase();
20495
+ if (addr) underlyingToUid.set(addr, uid);
20496
+ }
20497
+ }
20265
20498
  let totalDebt24h = 0;
20266
20499
  let totalDeposits24h = 0;
20267
20500
  for (let i = 0; i < reserveEntries.length; i++) {
20268
- const { hub, underlying } = reserveEntries[i];
20269
- const refAddress = `${hub}:${underlying}`;
20270
- const key = createMarketUid(chainId, lender, refAddress);
20501
+ const { hub, underlying, spokeAddr } = reserveEntries[i];
20502
+ let key;
20503
+ if (hub) {
20504
+ key = createMarketUid(chainId, lender, `${hub}:${underlying}`);
20505
+ } else {
20506
+ key = underlyingToUid.get(underlying) ?? createMarketUid(chainId, lender, `:${underlying}`);
20507
+ }
20271
20508
  const metaEntity = metaMap?.[key];
20272
20509
  if (!metaEntity) continue;
20273
20510
  const base = i * USER_CALLS_PER_RESERVE;
@@ -20278,6 +20515,11 @@ var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20278
20515
  metaEntity
20279
20516
  );
20280
20517
  if (!dataForAsset) continue;
20518
+ const userPositionResult = data[base + 3];
20519
+ const userDynConfigKey = Number(
20520
+ userPositionResult?.dynamicConfigKey ?? 0
20521
+ );
20522
+ dataForAsset.userConfigKey = `${spokeAddr.toLowerCase()}:${userDynConfigKey}`;
20281
20523
  totalDebt24h += addedDebt;
20282
20524
  totalDeposits24h += addedDeposits;
20283
20525
  lendingPositions[key] = dataForAsset;
@@ -20286,10 +20528,8 @@ var getAaveV4UserDataConverter = (lender, chainId, account, metaMap) => {
20286
20528
  chainId,
20287
20529
  account,
20288
20530
  lendingPositions,
20289
- rewards: [],
20290
- userEMode: 0
20291
- };
20292
- const userData = createBaseTypeUserState(
20531
+ rewards: []};
20532
+ const userData = createAaveV4UserState(
20293
20533
  payload,
20294
20534
  metaMap,
20295
20535
  totalDeposits24h,