@suilend/sdk 13.6.0 → 13.7.0-next.ge2ee95d

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.
@@ -651,7 +651,7 @@ export type ReserveAssetDataEventJSON = {
651
651
  /**
652
652
  * Deprecated: this struct's layout is frozen by Sui's upgrade-compatibility check, since
653
653
  * it is already published on mainnet. Use `ReserveAssetDataEventV2` instead, which carries
654
- * every field here plus `conf`.
654
+ * every field here plus `conf` and the unclamped prices.
655
655
  */
656
656
  export declare class ReserveAssetDataEvent implements StructClass {
657
657
  __StructClass: true;
@@ -717,6 +717,8 @@ export interface ReserveAssetDataEventV2Fields {
717
717
  smoothedPrice: ToField<Decimal>;
718
718
  priceLastUpdateTimestampS: ToField<'u64'>;
719
719
  conf: ToField<Decimal>;
720
+ unclampedPrice: ToField<Decimal>;
721
+ unclampedSmoothedPrice: ToField<Decimal>;
720
722
  }
721
723
  export type ReserveAssetDataEventV2Reified = Reified<ReserveAssetDataEventV2, ReserveAssetDataEventV2Fields>;
722
724
  export type ReserveAssetDataEventV2JSONField = {
@@ -737,6 +739,8 @@ export type ReserveAssetDataEventV2JSONField = {
737
739
  smoothedPrice: ToJSON<Decimal>;
738
740
  priceLastUpdateTimestampS: string;
739
741
  conf: ToJSON<Decimal>;
742
+ unclampedPrice: ToJSON<Decimal>;
743
+ unclampedSmoothedPrice: ToJSON<Decimal>;
740
744
  };
741
745
  export type ReserveAssetDataEventV2JSON = {
742
746
  $typeName: typeof ReserveAssetDataEventV2.$typeName;
@@ -768,6 +772,8 @@ export declare class ReserveAssetDataEventV2 implements StructClass {
768
772
  readonly smoothedPrice: ToField<Decimal>;
769
773
  readonly priceLastUpdateTimestampS: ToField<'u64'>;
770
774
  readonly conf: ToField<Decimal>;
775
+ readonly unclampedPrice: ToField<Decimal>;
776
+ readonly unclampedSmoothedPrice: ToField<Decimal>;
771
777
  private constructor();
772
778
  static reified(): ReserveAssetDataEventV2Reified;
773
779
  static get r(): ReserveAssetDataEventV2Reified;
@@ -1757,7 +1757,7 @@ export function isReserveAssetDataEvent(type) {
1757
1757
  /**
1758
1758
  * Deprecated: this struct's layout is frozen by Sui's upgrade-compatibility check, since
1759
1759
  * it is already published on mainnet. Use `ReserveAssetDataEventV2` instead, which carries
1760
- * every field here plus `conf`.
1760
+ * every field here plus `conf` and the unclamped prices.
1761
1761
  */
1762
1762
  export class ReserveAssetDataEvent {
1763
1763
  __StructClass = true;
@@ -2020,6 +2020,8 @@ export class ReserveAssetDataEventV2 {
2020
2020
  smoothedPrice;
2021
2021
  priceLastUpdateTimestampS;
2022
2022
  conf;
2023
+ unclampedPrice;
2024
+ unclampedSmoothedPrice;
2023
2025
  constructor(typeArgs, fields) {
2024
2026
  this.$fullTypeName = composeSuiType(ReserveAssetDataEventV2.$typeName, ...typeArgs);
2025
2027
  this.$typeArgs = typeArgs;
@@ -2040,6 +2042,8 @@ export class ReserveAssetDataEventV2 {
2040
2042
  this.smoothedPrice = fields.smoothedPrice;
2041
2043
  this.priceLastUpdateTimestampS = fields.priceLastUpdateTimestampS;
2042
2044
  this.conf = fields.conf;
2045
+ this.unclampedPrice = fields.unclampedPrice;
2046
+ this.unclampedSmoothedPrice = fields.unclampedSmoothedPrice;
2043
2047
  }
2044
2048
  static reified() {
2045
2049
  const reifiedBcs = ReserveAssetDataEventV2.bcs;
@@ -2101,6 +2105,8 @@ export class ReserveAssetDataEventV2 {
2101
2105
  smoothed_price: Decimal.bcs,
2102
2106
  price_last_update_timestamp_s: bcs.u64(),
2103
2107
  conf: Decimal.bcs,
2108
+ unclamped_price: Decimal.bcs,
2109
+ unclamped_smoothed_price: Decimal.bcs,
2104
2110
  });
2105
2111
  }
2106
2112
  static cachedBcs = null;
@@ -2129,6 +2135,8 @@ export class ReserveAssetDataEventV2 {
2129
2135
  smoothedPrice: decodeFromFields(Decimal.reified(), fields.smoothed_price),
2130
2136
  priceLastUpdateTimestampS: decodeFromFields('u64', fields.price_last_update_timestamp_s),
2131
2137
  conf: decodeFromFields(Decimal.reified(), fields.conf),
2138
+ unclampedPrice: decodeFromFields(Decimal.reified(), fields.unclamped_price),
2139
+ unclampedSmoothedPrice: decodeFromFields(Decimal.reified(), fields.unclamped_smoothed_price),
2132
2140
  });
2133
2141
  }
2134
2142
  static fromFieldsWithTypes(item) {
@@ -2153,6 +2161,8 @@ export class ReserveAssetDataEventV2 {
2153
2161
  smoothedPrice: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.smoothed_price),
2154
2162
  priceLastUpdateTimestampS: decodeFromFieldsWithTypes('u64', item.fields.price_last_update_timestamp_s),
2155
2163
  conf: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.conf),
2164
+ unclampedPrice: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.unclamped_price),
2165
+ unclampedSmoothedPrice: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.unclamped_smoothed_price),
2156
2166
  });
2157
2167
  }
2158
2168
  static fromBcs(data) {
@@ -2177,6 +2187,8 @@ export class ReserveAssetDataEventV2 {
2177
2187
  smoothedPrice: this.smoothedPrice.toJSONField(),
2178
2188
  priceLastUpdateTimestampS: this.priceLastUpdateTimestampS.toString(),
2179
2189
  conf: this.conf.toJSONField(),
2190
+ unclampedPrice: this.unclampedPrice.toJSONField(),
2191
+ unclampedSmoothedPrice: this.unclampedSmoothedPrice.toJSONField(),
2180
2192
  };
2181
2193
  }
2182
2194
  toJSON() {
@@ -2201,6 +2213,8 @@ export class ReserveAssetDataEventV2 {
2201
2213
  smoothedPrice: decodeFromJSONField(Decimal.reified(), field.smoothedPrice),
2202
2214
  priceLastUpdateTimestampS: decodeFromJSONField('u64', field.priceLastUpdateTimestampS),
2203
2215
  conf: decodeFromJSONField(Decimal.reified(), field.conf),
2216
+ unclampedPrice: decodeFromJSONField(Decimal.reified(), field.unclampedPrice),
2217
+ unclampedSmoothedPrice: decodeFromJSONField(Decimal.reified(), field.unclampedSmoothedPrice),
2204
2218
  });
2205
2219
  }
2206
2220
  static fromJSON(json) {
package/client.d.ts CHANGED
@@ -3,6 +3,7 @@ import { SuiGrpcClient } from "@mysten/sui/grpc";
3
3
  import { Transaction, TransactionArgument, TransactionObjectArgument, TransactionObjectInput } from "@mysten/sui/transactions";
4
4
  import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
5
5
  import BigNumber from "bignumber.js";
6
+ import { Decimal } from "./_generated/suilend/decimal/structs";
6
7
  import { LendingMarket, ObligationOwnerCap } from "./_generated/suilend/lending-market/structs";
7
8
  import { Obligation } from "./_generated/suilend/obligation/structs";
8
9
  import { NewConfigArgs as CreateRateLimiterConfigArgs } from "./_generated/suilend/rate-limiter/functions";
@@ -104,6 +105,11 @@ export declare class SuilendClient {
104
105
  static getReserveConfidenceMultiplierBps(suiGrpcClient: SuiGrpcClient, additionalFieldsBagId: string): Promise<BigNumber>;
105
106
  /** A reserve's stored Pyth confidence (the `ConfidenceKey` dynamic field on `reserve.id` directly, not inside `config.additionalFields`). Reads as 0 until the reserve's first price update writes it. */
106
107
  static getReserveStoredConfidence(suiGrpcClient: SuiGrpcClient, reserveId: string): Promise<BigNumber>;
108
+ /** The raw spot and EMA of the reserve's last refresh under a price guard (the `RawPriceKey` dynamic field on `reserve.id`). Undefined until its first refresh under a guard. Attach them with `withUnclampedPrices` only to a reserve as stored on chain, never to one a feed refresh has repriced. */
109
+ static getReserveRawPrices(suiGrpcClient: SuiGrpcClient, reserveId: string): Promise<{
110
+ price: Decimal;
111
+ smoothedPrice: Decimal;
112
+ } | undefined>;
107
113
  static createNewLendingMarket(registryId: string, lendingMarketType: string, transaction: Transaction): {
108
114
  NestedResult: [number, number];
109
115
  $kind: "NestedResult";
@@ -128,6 +134,13 @@ export declare class SuilendClient {
128
134
  claimRewardsAndDeposit(ownerId: string, obligationOwnerCap: TransactionObjectInput, rewards: ClaimRewardsReward[], transaction: Transaction): Transaction;
129
135
  findReserveArrayIndex(coinType: string): bigint;
130
136
  private submitReserveConfigUpdate;
137
+ /**
138
+ * From market version 8, sets every `CreateReserveConfigArgs` field on a
139
+ * builder seeded from the reserve's live config, so `additionalFields`
140
+ * entries (confidence multiplier, oracle thresholds, stable pause) keep
141
+ * their current values: version 8 installs only `build` output. At version
142
+ * 7 it replaces the whole config, which resets those entries.
143
+ */
131
144
  updateReserveConfig(lendingMarketOwnerCapId: string, transaction: Transaction, coinType: string, createReserveConfigArgs: CreateReserveConfigArgs): import("@mysten/sui/transactions").TransactionResult;
132
145
  /**
133
146
  * Updates a subset of a reserve's config fields, leaving every unspecified
package/client.js CHANGED
@@ -478,6 +478,21 @@ export class SuilendClient {
478
478
  });
479
479
  return decimalToBigNumber(Decimal.fromBcs(dynamicField.value.bcs));
480
480
  }
481
+ /** The raw spot and EMA of the reserve's last refresh under a price guard (the `RawPriceKey` dynamic field on `reserve.id`). Undefined until its first refresh under a guard. Attach them with `withUnclampedPrices` only to a reserve as stored on chain, never to one a feed refresh has repriced. */
482
+ static async getReserveRawPrices(suiGrpcClient, reserveId) {
483
+ const match = await findBagEntryByTypeSuffix(suiGrpcClient, reserveId, "::reserve::RawPriceKey");
484
+ if (!match)
485
+ return undefined;
486
+ const { dynamicField } = await suiGrpcClient.getDynamicField({
487
+ parentId: reserveId,
488
+ name: match.name,
489
+ });
490
+ const bytes = dynamicField.value.bcs;
491
+ return {
492
+ price: Decimal.fromBcs(bytes.slice(0, 32)),
493
+ smoothedPrice: Decimal.fromBcs(bytes.slice(32, 64)),
494
+ };
495
+ }
481
496
  static createNewLendingMarket(registryId, lendingMarketType, transaction) {
482
497
  const [ownerCap, lendingMarket] = createLendingMarket(transaction, lendingMarketType, transaction.object(registryId));
483
498
  transaction.moveCall({
@@ -650,9 +665,19 @@ export class SuilendClient {
650
665
  config: transaction.object(config),
651
666
  });
652
667
  }
668
+ /**
669
+ * From market version 8, sets every `CreateReserveConfigArgs` field on a
670
+ * builder seeded from the reserve's live config, so `additionalFields`
671
+ * entries (confidence multiplier, oracle thresholds, stable pause) keep
672
+ * their current values: version 8 installs only `build` output. At version
673
+ * 7 it replaces the whole config, which resets those entries.
674
+ */
653
675
  updateReserveConfig(lendingMarketOwnerCapId, transaction, coinType, createReserveConfigArgs) {
654
- const [config] = createReserveConfig(transaction, createReserveConfigArgs);
655
- return this.submitReserveConfigUpdate(lendingMarketOwnerCapId, transaction, coinType, config);
676
+ if (this.lendingMarket.version < 8n) {
677
+ const [config] = createReserveConfig(transaction, createReserveConfigArgs);
678
+ return this.submitReserveConfigUpdate(lendingMarketOwnerCapId, transaction, coinType, config);
679
+ }
680
+ return this.patchReserveConfig(lendingMarketOwnerCapId, transaction, coinType, createReserveConfigArgs);
656
681
  }
657
682
  /**
658
683
  * Updates a subset of a reserve's config fields, leaving every unspecified
package/lib/types.d.ts CHANGED
@@ -51,6 +51,8 @@ export type ApiReserveAssetDataEvent = {
51
51
  smoothedPrice: string;
52
52
  priceLastUpdateTimestampS: number;
53
53
  conf: string | null;
54
+ unclampedPrice: string | null;
55
+ unclampedSmoothedPrice: string | null;
54
56
  timestamp: number;
55
57
  digest: string;
56
58
  eventIndex: number;
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@suilend/sdk","version":"13.6.0","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/interpolate":"./utils/interpolate.js","./utils/obligation":"./utils/obligation.js","./utils/priceGuard":"./utils/priceGuard.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.7.0","@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.2","@mysten/sui":"2.35.0","@suilend/sui-core":"2.2.0","@tsconfig/recommended":"1.0.13","@types/bn.js":"5.2.0","@types/lodash":"4.17.25","@types/node":"26.6.4","fast-check":"4.10.2","prettier":"3.9.9","ts-node":"10.9.2","typescript":"6.0.3","vite":"8.3.2","vitest":"5.0.3"},"peerDependencies":{"@mysten/bcs":"^2.1.1","@mysten/sui":">=2.31.3 <3","@suilend/sui-core":"^2.0.1"},"type":"module"}
1
+ {"name":"@suilend/sdk","version":"13.7.0-next.ge2ee95d","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/interpolate":"./utils/interpolate.js","./utils/obligation":"./utils/obligation.js","./utils/priceGuard":"./utils/priceGuard.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.7.0","@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.2","@mysten/sui":"2.35.0","@suilend/sui-core":"2.2.0","@tsconfig/recommended":"1.0.13","@types/bn.js":"5.2.0","@types/lodash":"4.17.26","@types/node":"26.6.5","fast-check":"4.10.2","prettier":"3.9.10","ts-node":"10.9.2","typescript":"6.0.3","vite":"8.3.4","vitest":"5.0.4"},"peerDependencies":{"@mysten/bcs":"^2.1.1","@mysten/sui":">=2.31.3 <3","@suilend/sui-core":"^2.0.1"},"type":"module"}
@@ -30,7 +30,14 @@ kBps = ZERO_K_BPS) => {
30
30
  // Null conf (a pre-upgrade event) has no margin to apply -- 0 reproduces
31
31
  // plain min/max exactly, same as kBps=0 does.
32
32
  const conf = event.conf ? new BigNumber(event.conf).div(WAD) : new BigNumber(0);
33
- const { lowerBound: minPrice, upperBound: maxPrice } = applyConfidenceMargin(price, smoothedPrice, conf, kBps);
33
+ const unclampedPrice = event.unclampedPrice
34
+ ? new BigNumber(event.unclampedPrice).div(WAD)
35
+ : price;
36
+ const unclampedSmoothedPrice = event.unclampedSmoothedPrice
37
+ ? new BigNumber(event.unclampedSmoothedPrice).div(WAD)
38
+ : smoothedPrice;
39
+ const rangePrices = [price, smoothedPrice, unclampedPrice, unclampedSmoothedPrice];
40
+ const { lowerBound: minPrice, upperBound: maxPrice } = applyConfidenceMargin(BigNumber.min(...rangePrices), BigNumber.max(...rangePrices), conf, kBps, unclampedPrice);
34
41
  // Custom
35
42
  const utilizationPercent = depositedAmount.eq(0)
36
43
  ? new BigNumber(0)
@@ -10,7 +10,8 @@ export const parseReserve = (reserve, coinMetadataMap,
10
10
  // ReserveConfig.additionalFields Bag entry respectively, neither of which
11
11
  // lives on the Reserve object's own BCS content, so this parser can't
12
12
  // fetch them itself without becoming async. Omit either (or both) for
13
- // plain min/max(price, smoothedPrice) bounds.
13
+ // plain bounds. The raw prices of a guarded reserve come attached with
14
+ // simulate.withUnclampedPrices.
14
15
  conf, kBps) => {
15
16
  const config = parseReserveConfig(reserve);
16
17
  const $typeName = reserve.$typeName;
@@ -22,11 +23,8 @@ conf, kBps) => {
22
23
  const priceIdentifier = `0x${toHexString(reserve.priceIdentifier.bytes)}`;
23
24
  const price = new BigNumber(reserve.price.value.toString()).div(WAD);
24
25
  const smoothedPrice = new BigNumber(reserve.smoothedPrice.value.toString()).div(WAD);
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;
26
+ const { low, high } = simulate.priceRange(reserve);
27
+ const { lowerBound: minPrice, upperBound: maxPrice } = simulate.applyConfidenceMargin(low, high, conf !== undefined && kBps !== undefined ? conf : new BigNumber(0), kBps ?? new BigNumber(0), simulate.unclampedSpot(reserve));
30
28
  const priceLastUpdateTimestampS = reserve.priceLastUpdateTimestampS;
31
29
  const availableAmount = new BigNumber(reserve.availableAmount.toString()).div(10 ** mintDecimals);
32
30
  const ctokenSupply = new BigNumber(reserve.ctokenSupply.toString()).div(10 ** mintDecimals);
package/utils/events.d.ts CHANGED
@@ -8,6 +8,7 @@ type Decimal = {
8
8
  };
9
9
  type address = string;
10
10
  type u64 = string;
11
+ type u256 = string;
11
12
  export declare enum SuilendEventType {
12
13
  InterestUpdateEvent = "InterestUpdateEvent",
13
14
  ReserveAssetDataEvent = "ReserveAssetDataEvent",
@@ -73,20 +74,22 @@ export declare class ReserveAssetDataEventV2 extends TypedParamsSuiEvent<{
73
74
  lending_market_id: address;
74
75
  coin_type: TypeName;
75
76
  reserve_id: address;
76
- available_amount: Decimal;
77
- supply_amount: Decimal;
78
- borrowed_amount: Decimal;
79
- available_amount_usd_estimate: Decimal;
80
- supply_amount_usd_estimate: Decimal;
81
- borrowed_amount_usd_estimate: Decimal;
82
- borrow_apr: Decimal;
83
- supply_apr: Decimal;
77
+ available_amount: u256;
78
+ supply_amount: u256;
79
+ borrowed_amount: u256;
80
+ available_amount_usd_estimate: u256;
81
+ supply_amount_usd_estimate: u256;
82
+ borrowed_amount_usd_estimate: u256;
83
+ borrow_apr: u256;
84
+ supply_apr: u256;
84
85
  ctoken_supply: u64;
85
- cumulative_borrow_rate: Decimal;
86
- price: Decimal;
87
- smoothed_price: Decimal;
86
+ cumulative_borrow_rate: u256;
87
+ price: u256;
88
+ smoothed_price: u256;
88
89
  price_last_update_timestamp_s: u64;
89
- conf: Decimal;
90
+ conf: u256;
91
+ unclamped_price: u256;
92
+ unclamped_smoothed_price: u256;
90
93
  }> {
91
94
  }
92
95
  export declare class MintEvent extends TypedParamsSuiEvent<{
@@ -40,6 +40,13 @@ export interface FeedPrice {
40
40
  }
41
41
  export declare const feedConfidenceOf: (reserve: Reserve<string>) => BigNumber | undefined;
42
42
  export declare const withUnclampedPrices: (reserve: Reserve<string>, price: Decimal, smoothedPrice: Decimal) => Reserve<string>;
43
+ /** Mirrors reserve.move's `price_range`. */
44
+ export declare const priceRange: (reserve: Reserve<string>) => {
45
+ low: BigNumber;
46
+ high: BigNumber;
47
+ };
48
+ /** Mirrors reserve.move's `unclamped_price`: the spot a reserve's conf was quoted with. */
49
+ export declare const unclampedSpot: (reserve: Reserve<string>) => BigNumber;
43
50
  /**
44
51
  * A source of latest prices. Structural on purpose: any object with this method
45
52
  * qualifies, so a caller can inject its own client (authenticated, failover,
@@ -158,13 +165,16 @@ export declare const stringToDecimal: (value: string) => Decimal;
158
165
  export declare const decimalToBigNumber: (value: Decimal) => BigNumber;
159
166
  /**
160
167
  * Mirrors reserve.move's `price_lower_bound`/`price_upper_bound`: the one
161
- * off-chain place this formula lives. `conf` and `kBps` are the reserve's
162
- * stored Pyth confidence and its `ReserveConfig` confidence multiplier (in
163
- * bps, e.g. 30000 for a logical k=3) -- both plain human-scale BigNumbers,
164
- * not WAD-scaled Decimals. `kBps=0` disables the margin entirely: both
165
- * bounds collapse to plain `min`/`max(price, smoothedPrice)`.
168
+ * off-chain place this formula lives. `low` and `high` are the ends of the
169
+ * reserve's price range (`priceRange`), which the bounds widen by the share
170
+ * `k * conf / spot`, where `spot` is the unclamped spot of the same update
171
+ * `conf` came from. `conf` and `kBps` are the reserve's stored
172
+ * Pyth confidence and its `ReserveConfig` confidence multiplier (in bps, e.g.
173
+ * 30000 for a logical k=3) -- both plain human-scale BigNumbers, not
174
+ * WAD-scaled Decimals. `kBps=0` or `conf=0` disables the margin entirely:
175
+ * both bounds collapse to `low` and `high`.
166
176
  */
167
- export declare const applyConfidenceMargin: (price: BigNumber, smoothedPrice: BigNumber, conf: BigNumber, kBps: BigNumber) => {
177
+ export declare const applyConfidenceMargin: (low: BigNumber, high: BigNumber, conf: BigNumber, kBps: BigNumber, spot: BigNumber) => {
168
178
  lowerBound: BigNumber;
169
179
  upperBound: BigNumber;
170
180
  };
package/utils/simulate.js CHANGED
@@ -124,7 +124,7 @@ export const withUnclampedPrices = (reserve, price, smoothedPrice) => Object.ass
124
124
  unclampedPrices: { price, smoothedPrice },
125
125
  });
126
126
  /** Mirrors reserve.move's `price_range`. */
127
- const priceRange = (reserve) => {
127
+ export const priceRange = (reserve) => {
128
128
  const unclamped = reserve.unclampedPrices;
129
129
  const prices = [
130
130
  reserve.price,
@@ -133,6 +133,9 @@ const priceRange = (reserve) => {
133
133
  ].map(decimalToBigNumber);
134
134
  return { low: BigNumber.min(...prices), high: BigNumber.max(...prices) };
135
135
  };
136
+ /** Mirrors reserve.move's `unclamped_price`: the spot a reserve's conf was quoted with. */
137
+ export const unclampedSpot = (reserve) => decimalToBigNumber(reserve.unclampedPrices?.price ??
138
+ reserve.price);
136
139
  // Re-exported, not redefined: it was part of this module's public surface before
137
140
  // it moved to ./feedId, and every consumer that normalizes a feed id to compare
138
141
  // it against `unpricedCoinTypes` imports it from here.
@@ -432,8 +435,7 @@ confidenceByCoinType) {
432
435
  const confidence = resolveConfidence(normalizedConfidence?.get(normalizeStructTag(unrefreshedBorrow.coinType)), reserve);
433
436
  const { low, high } = priceRange(reserve);
434
437
  const upperBoundPrice = confidence !== undefined
435
- ? applyConfidenceMargin(low, high, confidence.conf, confidence.kBps)
436
- .upperBound
438
+ ? applyConfidenceMargin(low, high, confidence.conf, confidence.kBps, unclampedSpot(reserve)).upperBound
437
439
  : high;
438
440
  // `exactBorrowedAmount` (this borrow's own amount), not
439
441
  // `reserve.borrowedAmount`: the reserve field is the whole reserve's
@@ -492,16 +494,21 @@ export const decimalToBigNumber = (value) => {
492
494
  };
493
495
  /**
494
496
  * Mirrors reserve.move's `price_lower_bound`/`price_upper_bound`: the one
495
- * off-chain place this formula lives. `conf` and `kBps` are the reserve's
496
- * stored Pyth confidence and its `ReserveConfig` confidence multiplier (in
497
- * bps, e.g. 30000 for a logical k=3) -- both plain human-scale BigNumbers,
498
- * not WAD-scaled Decimals. `kBps=0` disables the margin entirely: both
499
- * bounds collapse to plain `min`/`max(price, smoothedPrice)`.
497
+ * off-chain place this formula lives. `low` and `high` are the ends of the
498
+ * reserve's price range (`priceRange`), which the bounds widen by the share
499
+ * `k * conf / spot`, where `spot` is the unclamped spot of the same update
500
+ * `conf` came from. `conf` and `kBps` are the reserve's stored
501
+ * Pyth confidence and its `ReserveConfig` confidence multiplier (in bps, e.g.
502
+ * 30000 for a logical k=3) -- both plain human-scale BigNumbers, not
503
+ * WAD-scaled Decimals. `kBps=0` or `conf=0` disables the margin entirely:
504
+ * both bounds collapse to `low` and `high`.
500
505
  */
501
- export const applyConfidenceMargin = (price, smoothedPrice, conf, kBps) => {
502
- const margin = kBps.dividedBy(10_000).multipliedBy(conf);
503
- const lowerBound = BigNumber.max(BigNumber.min(price, smoothedPrice).minus(margin), new BigNumber(0));
504
- const upperBound = BigNumber.max(price, smoothedPrice).plus(margin);
506
+ export const applyConfidenceMargin = (low, high, conf, kBps, spot) => {
507
+ if (kBps.isZero() || conf.isZero())
508
+ return { lowerBound: low, upperBound: high };
509
+ const fraction = kBps.dividedBy(10_000).multipliedBy(conf).dividedBy(spot);
510
+ const lowerBound = BigNumber.max(low.minus(low.multipliedBy(fraction)), new BigNumber(0));
511
+ const upperBound = high.plus(high.multipliedBy(fraction));
505
512
  return { lowerBound, upperBound };
506
513
  };
507
514
  export const getCTokenMarketValue = (reserve, depositedCTokenAmount) => {
@@ -518,7 +525,8 @@ conf, kBps) => {
518
525
  const liquidityAmount = depositedCTokenAmount.multipliedBy(cTokenRatio(reserve));
519
526
  const { low, high } = priceRange(reserve);
520
527
  const lowerBoundPrice = conf !== undefined && kBps !== undefined
521
- ? applyConfidenceMargin(low, high, conf, kBps).lowerBound
528
+ ? applyConfidenceMargin(low, high, conf, kBps, unclampedSpot(reserve))
529
+ .lowerBound
522
530
  : low;
523
531
  return lowerBoundPrice
524
532
  .multipliedBy(liquidityAmount)