@suilend/sdk 13.1.0-next.g093f417 → 13.1.0-next.g1db8a54

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/lib/pyth.js CHANGED
@@ -103,6 +103,7 @@ export const createHermesPriceFeedSource = (hermesClient) => {
103
103
  id: parsed.id,
104
104
  price: toPriceNumber(parsed.price),
105
105
  emaPrice: toPriceNumber(parsed.ema_price),
106
+ conf: toPriceNumber({ price: parsed.price.conf, expo: parsed.price.expo }),
106
107
  publishTimeS: parsed.price.publish_time,
107
108
  }));
108
109
  };
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@suilend/sdk","version":"13.1.0-next.g093f417","private":false,"description":"A TypeScript SDK for interacting with the Suilend program","author":"Suilend","license":"MIT","main":"./index.js","exports":{".":"./index.js","./client":"./client.js","./mmt":"./mmt.js","./strategies":"./strategies.js","./api/events":"./api/events.js","./api":"./api/index.js","./lib/constants":"./lib/constants.js","./lib":"./lib/index.js","./lib/initialize":"./lib/initialize.js","./lib/liquidityMining":"./lib/liquidityMining.js","./lib/proCompatible":"./lib/proCompatible.js","./lib/pyth":"./lib/pyth.js","./lib/strategyOwnerCap":"./lib/strategyOwnerCap.js","./lib/transactions":"./lib/transactions.js","./lib/types":"./lib/types.js","./margin":"./margin/index.js","./parsers/apiReserveAssetDataEvent":"./parsers/apiReserveAssetDataEvent.js","./parsers":"./parsers/index.js","./parsers/lendingMarket":"./parsers/lendingMarket.js","./parsers/obligation":"./parsers/obligation.js","./parsers/rateLimiter":"./parsers/rateLimiter.js","./parsers/reserve":"./parsers/reserve.js","./swap":"./swap/index.js","./swap/quote":"./swap/quote.js","./swap/transaction":"./swap/transaction.js","./utils/events":"./utils/events.js","./utils/feedId":"./utils/feedId.js","./utils":"./utils/index.js","./utils/obligation":"./utils/obligation.js","./utils/simulate":"./utils/simulate.js","./_generated/_envs":"./_generated/_envs/index.js","./_generated/_envs/mainnet":"./_generated/_envs/mainnet.js","./_generated/_framework/env":"./_generated/_framework/env.js","./_generated/_framework/reified":"./_generated/_framework/reified.js","./_generated/_framework/util":"./_generated/_framework/util.js","./_generated/_framework/vector":"./_generated/_framework/vector.js","./_generated/suilend":"./_generated/suilend/index.js","./margin/margin/admin_cap":"./margin/margin/admin_cap.js","./margin/margin/market":"./margin/margin/market.js","./margin/margin/permissions":"./margin/margin/permissions.js","./margin/margin/position":"./margin/margin/position.js","./margin/margin/router":"./margin/margin/router.js","./margin/margin/version":"./margin/margin/version.js","./margin/utils":"./margin/utils/index.js","./_generated/suilend/cell/structs":"./_generated/suilend/cell/structs.js","./_generated/suilend/decimal/structs":"./_generated/suilend/decimal/structs.js","./_generated/suilend/lending-market/functions":"./_generated/suilend/lending-market/functions.js","./_generated/suilend/lending-market/structs":"./_generated/suilend/lending-market/structs.js","./_generated/suilend/lending-market-registry/functions":"./_generated/suilend/lending-market-registry/functions.js","./_generated/suilend/liquidity-mining/structs":"./_generated/suilend/liquidity-mining/structs.js","./_generated/suilend/obligation/structs":"./_generated/suilend/obligation/structs.js","./_generated/suilend/rate-limiter/functions":"./_generated/suilend/rate-limiter/functions.js","./_generated/suilend/rate-limiter/structs":"./_generated/suilend/rate-limiter/structs.js","./_generated/suilend/reserve/structs":"./_generated/suilend/reserve/structs.js","./_generated/suilend/reserve-config/functions":"./_generated/suilend/reserve-config/functions.js","./_generated/suilend/reserve-config/structs":"./_generated/suilend/reserve-config/structs.js","./_generated/_dependencies/pyth-2/price-identifier/structs":"./_generated/_dependencies/pyth-2/price-identifier/structs.js","./_generated/_dependencies/std/ascii/structs":"./_generated/_dependencies/std/ascii/structs.js","./_generated/_dependencies/std/option/structs":"./_generated/_dependencies/std/option/structs.js","./_generated/_dependencies/std/type-name/structs":"./_generated/_dependencies/std/type-name/structs.js","./_generated/_dependencies/sui/bag/structs":"./_generated/_dependencies/sui/bag/structs.js","./_generated/_dependencies/sui/balance/structs":"./_generated/_dependencies/sui/balance/structs.js","./_generated/_dependencies/sui/object/structs":"./_generated/_dependencies/sui/object/structs.js","./_generated/_dependencies/sui/object-table/structs":"./_generated/_dependencies/sui/object-table/structs.js","./margin/margin/deps/std/type_name":"./margin/margin/deps/std/type_name.js","./margin/margin/deps/sui/vec_set":"./margin/margin/deps/sui/vec_set.js","./margin/margin/deps/suilend/lending_market":"./margin/margin/deps/suilend/lending_market.js"},"types":"./index.d.ts","scripts":{"codegen":"node ./codegen.js","codegen:install":"node ./install-codegen.js","build":"rm -rf ./dist && tsc && node ./fix-esm-imports.js","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.test.json","test":"vitest run","lint:ci":"yarn run typecheck","prettier":"prettier --write src/ tests/","release":"yarn run build && node ./release.js && cd ./dist && npm publish --access public"},"repository":{"type":"git","url":"git+https://github.com/fireflyprotocol/lending-mono.git","directory":"ts/sdks/sdk"},"dependencies":{"@bluefin-exchange/bluefin7k-aggregator-sdk":"7.6.3","@cetusprotocol/aggregator-sdk":"1.7.3","@flowx-finance/sdk":"2.1.0","@pythnetwork/hermes-client":"3.1.0","@pythnetwork/pyth-sui-js":"4.0.0","@suilend/springsui-sdk":"4.1.0","bignumber.js":"11.1.5","bn.js":"5.2.5","crypto-js":"4.2.0","lodash":"4.18.1","p-limit":"7.3.3","uuid":"14.0.2"},"devDependencies":{"@mysten/bcs":"2.1.1","@mysten/sui":"2.29.0","@suilend/sui-core":"2.1.0","@tsconfig/recommended":"1.0.13","@types/bn.js":"5.2.0","@types/lodash":"4.17.25","@types/node":"26.5.1","fast-check":"4.10.2","prettier":"3.9.9","ts-node":"10.9.2","typescript":"6.0.3","vite":"8.3.0","vitest":"5.0.1"},"peerDependencies":{"@mysten/bcs":"^2.1.1","@mysten/sui":">=2.22.1 <3","@suilend/sui-core":"^2.0.1"},"type":"module"}
1
+ {"name":"@suilend/sdk","version":"13.1.0-next.g1db8a54","private":false,"description":"A TypeScript SDK for interacting with the Suilend program","author":"Suilend","license":"MIT","main":"./index.js","exports":{".":"./index.js","./client":"./client.js","./mmt":"./mmt.js","./strategies":"./strategies.js","./api/events":"./api/events.js","./api":"./api/index.js","./lib/constants":"./lib/constants.js","./lib":"./lib/index.js","./lib/initialize":"./lib/initialize.js","./lib/liquidityMining":"./lib/liquidityMining.js","./lib/proCompatible":"./lib/proCompatible.js","./lib/pyth":"./lib/pyth.js","./lib/strategyOwnerCap":"./lib/strategyOwnerCap.js","./lib/transactions":"./lib/transactions.js","./lib/types":"./lib/types.js","./margin":"./margin/index.js","./parsers/apiReserveAssetDataEvent":"./parsers/apiReserveAssetDataEvent.js","./parsers":"./parsers/index.js","./parsers/lendingMarket":"./parsers/lendingMarket.js","./parsers/obligation":"./parsers/obligation.js","./parsers/rateLimiter":"./parsers/rateLimiter.js","./parsers/reserve":"./parsers/reserve.js","./swap":"./swap/index.js","./swap/quote":"./swap/quote.js","./swap/transaction":"./swap/transaction.js","./utils/events":"./utils/events.js","./utils/feedId":"./utils/feedId.js","./utils":"./utils/index.js","./utils/obligation":"./utils/obligation.js","./utils/simulate":"./utils/simulate.js","./_generated/_envs":"./_generated/_envs/index.js","./_generated/_envs/mainnet":"./_generated/_envs/mainnet.js","./_generated/_framework/env":"./_generated/_framework/env.js","./_generated/_framework/reified":"./_generated/_framework/reified.js","./_generated/_framework/util":"./_generated/_framework/util.js","./_generated/_framework/vector":"./_generated/_framework/vector.js","./_generated/suilend":"./_generated/suilend/index.js","./margin/margin/admin_cap":"./margin/margin/admin_cap.js","./margin/margin/market":"./margin/margin/market.js","./margin/margin/permissions":"./margin/margin/permissions.js","./margin/margin/position":"./margin/margin/position.js","./margin/margin/router":"./margin/margin/router.js","./margin/margin/version":"./margin/margin/version.js","./margin/utils":"./margin/utils/index.js","./_generated/suilend/cell/structs":"./_generated/suilend/cell/structs.js","./_generated/suilend/decimal/structs":"./_generated/suilend/decimal/structs.js","./_generated/suilend/lending-market/functions":"./_generated/suilend/lending-market/functions.js","./_generated/suilend/lending-market/structs":"./_generated/suilend/lending-market/structs.js","./_generated/suilend/lending-market-registry/functions":"./_generated/suilend/lending-market-registry/functions.js","./_generated/suilend/liquidity-mining/structs":"./_generated/suilend/liquidity-mining/structs.js","./_generated/suilend/obligation/structs":"./_generated/suilend/obligation/structs.js","./_generated/suilend/rate-limiter/functions":"./_generated/suilend/rate-limiter/functions.js","./_generated/suilend/rate-limiter/structs":"./_generated/suilend/rate-limiter/structs.js","./_generated/suilend/reserve/structs":"./_generated/suilend/reserve/structs.js","./_generated/suilend/reserve-config/functions":"./_generated/suilend/reserve-config/functions.js","./_generated/suilend/reserve-config/structs":"./_generated/suilend/reserve-config/structs.js","./_generated/_dependencies/pyth-2/price-identifier/structs":"./_generated/_dependencies/pyth-2/price-identifier/structs.js","./_generated/_dependencies/std/ascii/structs":"./_generated/_dependencies/std/ascii/structs.js","./_generated/_dependencies/std/option/structs":"./_generated/_dependencies/std/option/structs.js","./_generated/_dependencies/std/type-name/structs":"./_generated/_dependencies/std/type-name/structs.js","./_generated/_dependencies/sui/bag/structs":"./_generated/_dependencies/sui/bag/structs.js","./_generated/_dependencies/sui/balance/structs":"./_generated/_dependencies/sui/balance/structs.js","./_generated/_dependencies/sui/object/structs":"./_generated/_dependencies/sui/object/structs.js","./_generated/_dependencies/sui/object-table/structs":"./_generated/_dependencies/sui/object-table/structs.js","./margin/margin/deps/std/type_name":"./margin/margin/deps/std/type_name.js","./margin/margin/deps/sui/vec_set":"./margin/margin/deps/sui/vec_set.js","./margin/margin/deps/suilend/lending_market":"./margin/margin/deps/suilend/lending_market.js"},"types":"./index.d.ts","scripts":{"codegen":"node ./codegen.js","codegen:install":"node ./install-codegen.js","build":"rm -rf ./dist && tsc && node ./fix-esm-imports.js","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.test.json","test":"vitest run","lint:ci":"yarn run typecheck","prettier":"prettier --write src/ tests/","release":"yarn run build && node ./release.js && cd ./dist && npm publish --access public"},"repository":{"type":"git","url":"git+https://github.com/fireflyprotocol/lending-mono.git","directory":"ts/sdks/sdk"},"dependencies":{"@bluefin-exchange/bluefin7k-aggregator-sdk":"7.6.3","@cetusprotocol/aggregator-sdk":"1.7.3","@flowx-finance/sdk":"2.1.0","@pythnetwork/hermes-client":"3.1.0","@pythnetwork/pyth-sui-js":"4.0.0","@suilend/springsui-sdk":"4.1.0","bignumber.js":"11.1.5","bn.js":"5.2.5","crypto-js":"4.2.0","lodash":"4.18.1","p-limit":"7.3.3","uuid":"14.0.2"},"devDependencies":{"@mysten/bcs":"2.1.1","@mysten/sui":"2.29.0","@suilend/sui-core":"2.1.0","@tsconfig/recommended":"1.0.13","@types/bn.js":"5.2.0","@types/lodash":"4.17.25","@types/node":"26.5.1","fast-check":"4.10.2","prettier":"3.9.9","ts-node":"10.9.2","typescript":"6.0.3","vite":"8.3.0","vitest":"5.0.1"},"peerDependencies":{"@mysten/bcs":"^2.1.1","@mysten/sui":">=2.22.1 <3","@suilend/sui-core":"^2.0.1"},"type":"module"}
@@ -6,7 +6,7 @@ export type ParsedReserve = ReturnType<typeof parseReserve>;
6
6
  export type ParsedReserveConfig = ReturnType<typeof parseReserveConfig>;
7
7
  export type ParsedPoolRewardManager = ReturnType<typeof parsePoolRewardManager>;
8
8
  export type ParsedPoolReward = NonNullable<ReturnType<typeof parsePoolReward>>;
9
- export declare const parseReserve: (reserve: Reserve<string>, coinMetadataMap: Record<string, SuiClientTypes.CoinMetadata>) => {
9
+ export declare const parseReserve: (reserve: Reserve<string>, coinMetadataMap: Record<string, SuiClientTypes.CoinMetadata>, conf?: BigNumber, kBps?: BigNumber) => {
10
10
  config: {
11
11
  $typeName: `${string}::reserve_config::ReserveConfig`;
12
12
  openLtvPct: number;
@@ -4,7 +4,14 @@ import { v4 as uuidv4 } from "uuid";
4
4
  import { WAD } from "../lib/constants.js";
5
5
  import { toHexString } from "../utils/index.js";
6
6
  import * as simulate from "../utils/simulate.js";
7
- export const parseReserve = (reserve, coinMetadataMap) => {
7
+ export const parseReserve = (reserve, coinMetadataMap,
8
+ // The reserve's stored Pyth confidence and its CURRENT confidence
9
+ // multiplier (in bps) -- a ConfidenceKey dynamic field and a
10
+ // ReserveConfig.additionalFields Bag entry respectively, neither of which
11
+ // lives on the Reserve object's own BCS content, so this parser can't
12
+ // fetch them itself without becoming async. Omit either (or both) for
13
+ // plain min/max(price, smoothedPrice) bounds.
14
+ conf, kBps) => {
8
15
  const config = parseReserveConfig(reserve);
9
16
  const $typeName = reserve.$typeName;
10
17
  const id = reserve.id;
@@ -15,8 +22,11 @@ export const parseReserve = (reserve, coinMetadataMap) => {
15
22
  const priceIdentifier = `0x${toHexString(reserve.priceIdentifier.bytes)}`;
16
23
  const price = new BigNumber(reserve.price.value.toString()).div(WAD);
17
24
  const smoothedPrice = new BigNumber(reserve.smoothedPrice.value.toString()).div(WAD);
18
- const minPrice = BigNumber.min(price, smoothedPrice);
19
- const maxPrice = BigNumber.max(price, smoothedPrice);
25
+ const bounds = conf !== undefined && kBps !== undefined
26
+ ? simulate.applyConfidenceMargin(price, smoothedPrice, conf, kBps)
27
+ : { lowerBound: BigNumber.min(price, smoothedPrice), upperBound: BigNumber.max(price, smoothedPrice) };
28
+ const minPrice = bounds.lowerBound;
29
+ const maxPrice = bounds.upperBound;
20
30
  const priceLastUpdateTimestampS = reserve.priceLastUpdateTimestampS;
21
31
  const availableAmount = new BigNumber(reserve.availableAmount.toString()).div(10 ** mintDecimals);
22
32
  const ctokenSupply = new BigNumber(reserve.ctokenSupply.toString()).div(10 ** mintDecimals);
@@ -35,7 +35,10 @@ export interface FeedPrice {
35
35
  price: number;
36
36
  emaPrice: number;
37
37
  publishTimeS: number;
38
+ /** Pyth's confidence interval for `price`, in the same units as `price`. */
39
+ conf?: number;
38
40
  }
41
+ export declare const feedConfidenceOf: (reserve: Reserve<string>) => BigNumber | undefined;
39
42
  /**
40
43
  * A source of latest prices. Structural on purpose: any object with this method
41
44
  * qualifies, so a caller can inject its own client (authenticated, failover,
@@ -144,7 +147,10 @@ export type ObligationRefresh = {
144
147
  * shallow-copied), silently corrupting `unrefreshedObligation` for anyone still
145
148
  * holding a reference to it.
146
149
  */
147
- export declare function computeObligationRefresh(obligation: Obligation<string>, refreshedReserves: Reserve<string>[], nowMs: number): ObligationRefresh;
150
+ export declare function computeObligationRefresh(obligation: Obligation<string>, refreshedReserves: Reserve<string>[], nowMs: number, confidenceByCoinType?: Map<string, {
151
+ conf?: BigNumber;
152
+ kBps: BigNumber;
153
+ }>): ObligationRefresh;
148
154
  export declare const refreshObligation: (unrefreshedObligation: Obligation<string>, refreshedReserves: Reserve<string>[]) => Obligation<string>;
149
155
  export declare const numberToDecimal: (value: number) => Decimal;
150
156
  export declare const stringToDecimal: (value: string) => Decimal;
@@ -162,7 +168,7 @@ export declare const applyConfidenceMargin: (price: BigNumber, smoothedPrice: Bi
162
168
  upperBound: BigNumber;
163
169
  };
164
170
  export declare const getCTokenMarketValue: (reserve: Reserve<string>, depositedCTokenAmount: BigNumber) => BigNumber;
165
- export declare const getCTokenMarketValueLowerBound: (reserve: Reserve<string>, depositedCTokenAmount: BigNumber) => BigNumber;
171
+ export declare const getCTokenMarketValueLowerBound: (reserve: Reserve<string>, depositedCTokenAmount: BigNumber, conf?: BigNumber, kBps?: BigNumber) => BigNumber;
166
172
  export declare const cTokenRatio: (reserve: Reserve<string>) => BigNumber;
167
173
  export declare const totalSupply: (reserve: Reserve<string>) => BigNumber;
168
174
  export declare const compoundBorrowedAmount: (snapshotAmount: BigNumber, currentCumulativeBorrowRate: BigNumber, snapshotCumulativeBorrowRate: BigNumber) => BigNumber;
package/utils/simulate.js CHANGED
@@ -119,6 +119,7 @@ export const updatePoolRewardsManager = (manager, nowMs) => {
119
119
  updatedManager.lastUpdateTimeMs = BigInt(nowMs);
120
120
  return updatedManager;
121
121
  };
122
+ export const feedConfidenceOf = (reserve) => reserve.feedConfidence;
122
123
  // Re-exported, not redefined: it was part of this module's public surface before
123
124
  // it moved to ./feedId, and every consumer that normalizes a feed id to compare
124
125
  // it against `unpricedCoinTypes` imports it from here.
@@ -158,6 +159,8 @@ const withFeedPrice = (reserve, priceFeed) => {
158
159
  newReserve.price = stringToDecimal(priceFeed.price.toString());
159
160
  newReserve.smoothedPrice = stringToDecimal(priceFeed.emaPrice.toString());
160
161
  newReserve.priceLastUpdateTimestampS = BigInt(priceFeed.publishTimeS);
162
+ newReserve.feedConfidence =
163
+ priceFeed.conf === undefined ? undefined : new BigNumber(priceFeed.conf);
161
164
  return newReserve;
162
165
  };
163
166
  export const reservePriceFeedIds = (reserves) => Array.from(new Set(reserves.map(reserveFeedId)));
@@ -332,6 +335,19 @@ export const findReserveOrThrow = (reserves, coinType) => {
332
335
  // (`v * WAD / 10_000`); dividing in BigNumber here matches that.
333
336
  export const computeBorrowWeight = (config) => new BigNumber(config.borrowWeightBps.toString()).div(10000);
334
337
  export const computeCloseLtv = (config) => new BigNumber(config.closeLtvPct / 100);
338
+ const resolveConfidence = (entry, reserve) => {
339
+ if (entry === undefined)
340
+ return undefined;
341
+ const refreshedFromFeed = "feedConfidence" in reserve;
342
+ const conf = feedConfidenceOf(reserve) ??
343
+ (refreshedFromFeed ? undefined : entry.conf) ??
344
+ (entry.kBps.isZero() ? new BigNumber(0) : undefined);
345
+ if (conf === undefined)
346
+ throw new Error(refreshedFromFeed
347
+ ? `Reserve ${reserve.coinType} was refreshed from a feed without conf, so the stored conf is from a different update: use a feed that carries conf`
348
+ : `No conf for reserve ${reserve.coinType}: refresh it from a feed that carries conf, or supply conf in the entry`);
349
+ return { conf, kBps: entry.kBps };
350
+ };
335
351
  /**
336
352
  * Pure computation half of `refreshObligation`: same math, but returns fresh
337
353
  * deposits/borrows/reward-manager arrays and the five USD aggregates instead
@@ -341,7 +357,20 @@ export const computeCloseLtv = (config) => new BigNumber(config.closeLtvPct / 10
341
357
  * shallow-copied), silently corrupting `unrefreshedObligation` for anyone still
342
358
  * holding a reference to it.
343
359
  */
344
- export function computeObligationRefresh(obligation, refreshedReserves, nowMs) {
360
+ export function computeObligationRefresh(obligation, refreshedReserves, nowMs,
361
+ // Per-reserve CURRENT confidence multiplier, keyed by coinType in either
362
+ // raw or normalized form. `conf` is the fallback for a reserve that was never
363
+ // price-refreshed; a reserve refreshed from a feed without `conf` throws
364
+ // instead (unless kBps is 0), because its price and the stored conf come from
365
+ // different updates. A reserve's own `feedConfidence` takes precedence because
366
+ // it comes from the same update as its price. A reserve with no entry here
367
+ // gets plain min/max(price, smoothedPrice) bounds.
368
+ confidenceByCoinType) {
369
+ const normalizedConfidence = confidenceByCoinType &&
370
+ new Map([...confidenceByCoinType].map(([coinType, entry]) => [
371
+ normalizeStructTag(coinType),
372
+ entry,
373
+ ]));
345
374
  const userRewardManagers = [...obligation.userRewardManagers];
346
375
  let depositValueUsd = new BigNumber(0);
347
376
  let allowedBorrowValueUsd = new BigNumber(0);
@@ -352,8 +381,9 @@ export function computeObligationRefresh(obligation, refreshedReserves, nowMs) {
352
381
  const config = reserve.config.element;
353
382
  userRewardManagers[Number(deposit.userRewardManagerIndex)] =
354
383
  updateUserRewardManager(reserve.depositsPoolRewardManager, userRewardManagers[Number(deposit.userRewardManagerIndex)], nowMs);
384
+ const confidence = resolveConfidence(normalizedConfidence?.get(normalizeStructTag(deposit.coinType)), reserve);
355
385
  const marketValue = getCTokenMarketValue(reserve, new BigNumber(deposit.depositedCtokenAmount.toString()));
356
- const marketValueLowerBound = getCTokenMarketValueLowerBound(reserve, new BigNumber(deposit.depositedCtokenAmount.toString()));
386
+ const marketValueLowerBound = getCTokenMarketValueLowerBound(reserve, new BigNumber(deposit.depositedCtokenAmount.toString()), confidence?.conf, confidence?.kBps);
357
387
  deposit.marketValue = stringToDecimal(marketValue.toString());
358
388
  depositValueUsd = depositValueUsd.plus(new BigNumber(marketValue.toString()));
359
389
  allowedBorrowValueUsd = allowedBorrowValueUsd.plus(marketValueLowerBound.multipliedBy(new BigNumber(config.openLtvPct / 100)));
@@ -385,7 +415,10 @@ export function computeObligationRefresh(obligation, refreshedReserves, nowMs) {
385
415
  const marketValue = exactBorrowedAmount
386
416
  .multipliedBy(decimalToBigNumber(reserve.price))
387
417
  .dividedBy(new BigNumber(10 ** reserve.mintDecimals));
388
- const upperBoundPrice = BigNumber.max(decimalToBigNumber(reserve.price), decimalToBigNumber(reserve.smoothedPrice));
418
+ const confidence = resolveConfidence(normalizedConfidence?.get(normalizeStructTag(unrefreshedBorrow.coinType)), reserve);
419
+ const upperBoundPrice = confidence !== undefined
420
+ ? applyConfidenceMargin(decimalToBigNumber(reserve.price), decimalToBigNumber(reserve.smoothedPrice), confidence.conf, confidence.kBps).upperBound
421
+ : BigNumber.max(decimalToBigNumber(reserve.price), decimalToBigNumber(reserve.smoothedPrice));
389
422
  // `exactBorrowedAmount` (this borrow's own amount), not
390
423
  // `reserve.borrowedAmount`: the reserve field is the whole reserve's
391
424
  // debt, so using it would scale every borrower's upper bound by total
@@ -461,10 +494,18 @@ export const getCTokenMarketValue = (reserve, depositedCTokenAmount) => {
461
494
  .multipliedBy(liquidityAmount)
462
495
  .dividedBy(new BigNumber(10 ** reserve.mintDecimals));
463
496
  };
464
- export const getCTokenMarketValueLowerBound = (reserve, depositedCTokenAmount) => {
497
+ export const getCTokenMarketValueLowerBound = (reserve, depositedCTokenAmount,
498
+ // The reserve's stored Pyth confidence and its CURRENT confidence
499
+ // multiplier (in bps). Omit either (or both) for the plain
500
+ // min(price, smoothedPrice) lower bound.
501
+ conf, kBps) => {
465
502
  const liquidityAmount = depositedCTokenAmount.multipliedBy(cTokenRatio(reserve));
466
- const price = BigNumber.min(decimalToBigNumber(reserve.price), decimalToBigNumber(reserve.smoothedPrice));
467
- return price
503
+ const price = reserve.price;
504
+ const smoothedPrice = reserve.smoothedPrice;
505
+ const lowerBoundPrice = conf !== undefined && kBps !== undefined
506
+ ? applyConfidenceMargin(decimalToBigNumber(price), decimalToBigNumber(smoothedPrice), conf, kBps).lowerBound
507
+ : BigNumber.min(decimalToBigNumber(price), decimalToBigNumber(smoothedPrice));
508
+ return lowerBoundPrice
468
509
  .multipliedBy(liquidityAmount)
469
510
  .dividedBy(new BigNumber(10 ** reserve.mintDecimals));
470
511
  };