@suilend/sdk 13.0.0 → 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.
@@ -648,6 +648,11 @@ export type ReserveAssetDataEventJSON = {
648
648
  $typeName: typeof ReserveAssetDataEvent.$typeName;
649
649
  $typeArgs: [];
650
650
  } & ReserveAssetDataEventJSONField;
651
+ /**
652
+ * Deprecated: this struct's layout is frozen by Sui's upgrade-compatibility check, since
653
+ * it is already published on mainnet. Use `ReserveAssetDataEventV2` instead, which carries
654
+ * every field here plus `conf`.
655
+ */
651
656
  export declare class ReserveAssetDataEvent implements StructClass {
652
657
  __StructClass: true;
653
658
  static get $typeName(): `${string}::reserve::ReserveAssetDataEvent`;
@@ -693,6 +698,96 @@ export declare class ReserveAssetDataEvent implements StructClass {
693
698
  }>): ReserveAssetDataEvent;
694
699
  static fetch(client: ClientWithCoreApi, id: string): Promise<ReserveAssetDataEvent>;
695
700
  }
701
+ export declare function isReserveAssetDataEventV2(type: string): boolean;
702
+ export interface ReserveAssetDataEventV2Fields {
703
+ lendingMarketId: ToField<'address'>;
704
+ coinType: ToField<TypeName>;
705
+ reserveId: ToField<'address'>;
706
+ availableAmount: ToField<Decimal>;
707
+ supplyAmount: ToField<Decimal>;
708
+ borrowedAmount: ToField<Decimal>;
709
+ availableAmountUsdEstimate: ToField<Decimal>;
710
+ supplyAmountUsdEstimate: ToField<Decimal>;
711
+ borrowedAmountUsdEstimate: ToField<Decimal>;
712
+ borrowApr: ToField<Decimal>;
713
+ supplyApr: ToField<Decimal>;
714
+ ctokenSupply: ToField<'u64'>;
715
+ cumulativeBorrowRate: ToField<Decimal>;
716
+ price: ToField<Decimal>;
717
+ smoothedPrice: ToField<Decimal>;
718
+ priceLastUpdateTimestampS: ToField<'u64'>;
719
+ conf: ToField<Decimal>;
720
+ }
721
+ export type ReserveAssetDataEventV2Reified = Reified<ReserveAssetDataEventV2, ReserveAssetDataEventV2Fields>;
722
+ export type ReserveAssetDataEventV2JSONField = {
723
+ lendingMarketId: string;
724
+ coinType: string;
725
+ reserveId: string;
726
+ availableAmount: ToJSON<Decimal>;
727
+ supplyAmount: ToJSON<Decimal>;
728
+ borrowedAmount: ToJSON<Decimal>;
729
+ availableAmountUsdEstimate: ToJSON<Decimal>;
730
+ supplyAmountUsdEstimate: ToJSON<Decimal>;
731
+ borrowedAmountUsdEstimate: ToJSON<Decimal>;
732
+ borrowApr: ToJSON<Decimal>;
733
+ supplyApr: ToJSON<Decimal>;
734
+ ctokenSupply: string;
735
+ cumulativeBorrowRate: ToJSON<Decimal>;
736
+ price: ToJSON<Decimal>;
737
+ smoothedPrice: ToJSON<Decimal>;
738
+ priceLastUpdateTimestampS: string;
739
+ conf: ToJSON<Decimal>;
740
+ };
741
+ export type ReserveAssetDataEventV2JSON = {
742
+ $typeName: typeof ReserveAssetDataEventV2.$typeName;
743
+ $typeArgs: [];
744
+ } & ReserveAssetDataEventV2JSONField;
745
+ export declare class ReserveAssetDataEventV2 implements StructClass {
746
+ __StructClass: true;
747
+ static get $typeName(): `${string}::reserve::ReserveAssetDataEventV2`;
748
+ static readonly $numTypeParams = 0;
749
+ static readonly $isPhantom: readonly [];
750
+ readonly $typeName: typeof ReserveAssetDataEventV2.$typeName;
751
+ readonly $fullTypeName: `${string}::reserve::ReserveAssetDataEventV2`;
752
+ readonly $typeArgs: [];
753
+ readonly $isPhantom: typeof ReserveAssetDataEventV2.$isPhantom;
754
+ readonly lendingMarketId: ToField<'address'>;
755
+ readonly coinType: ToField<TypeName>;
756
+ readonly reserveId: ToField<'address'>;
757
+ readonly availableAmount: ToField<Decimal>;
758
+ readonly supplyAmount: ToField<Decimal>;
759
+ readonly borrowedAmount: ToField<Decimal>;
760
+ readonly availableAmountUsdEstimate: ToField<Decimal>;
761
+ readonly supplyAmountUsdEstimate: ToField<Decimal>;
762
+ readonly borrowedAmountUsdEstimate: ToField<Decimal>;
763
+ readonly borrowApr: ToField<Decimal>;
764
+ readonly supplyApr: ToField<Decimal>;
765
+ readonly ctokenSupply: ToField<'u64'>;
766
+ readonly cumulativeBorrowRate: ToField<Decimal>;
767
+ readonly price: ToField<Decimal>;
768
+ readonly smoothedPrice: ToField<Decimal>;
769
+ readonly priceLastUpdateTimestampS: ToField<'u64'>;
770
+ readonly conf: ToField<Decimal>;
771
+ private constructor();
772
+ static reified(): ReserveAssetDataEventV2Reified;
773
+ static get r(): ReserveAssetDataEventV2Reified;
774
+ static phantom(): PhantomReified<ToTypeStr<ReserveAssetDataEventV2>>;
775
+ static get p(): PhantomReified<ToTypeStr<ReserveAssetDataEventV2>>;
776
+ private static instantiateBcs;
777
+ private static cachedBcs;
778
+ static get bcs(): ReturnType<typeof ReserveAssetDataEventV2.instantiateBcs>;
779
+ static fromFields(fields: Record<string, any>): ReserveAssetDataEventV2;
780
+ static fromFieldsWithTypes(item: FieldsWithTypes): ReserveAssetDataEventV2;
781
+ static fromBcs(data: Uint8Array): ReserveAssetDataEventV2;
782
+ toJSONField(): ReserveAssetDataEventV2JSONField;
783
+ toJSON(): ReserveAssetDataEventV2JSON;
784
+ static fromJSONField(field: any): ReserveAssetDataEventV2;
785
+ static fromJSON(json: Record<string, any>): ReserveAssetDataEventV2;
786
+ static fromCoreObject(obj: SuiClientTypes.Object<{
787
+ content: true;
788
+ }>): ReserveAssetDataEventV2;
789
+ static fetch(client: ClientWithCoreApi, id: string): Promise<ReserveAssetDataEventV2>;
790
+ }
696
791
  export declare function isClaimStakingRewardsEvent(type: string): boolean;
697
792
  export interface ClaimStakingRewardsEventFields {
698
793
  lendingMarketId: ToField<'address'>;
@@ -1754,6 +1754,11 @@ export function isReserveAssetDataEvent(type) {
1754
1754
  return type
1755
1755
  === `${getTypeOrigin('suilend', 'reserve::ReserveAssetDataEvent')}::reserve::ReserveAssetDataEvent`;
1756
1756
  }
1757
+ /**
1758
+ * Deprecated: this struct's layout is frozen by Sui's upgrade-compatibility check, since
1759
+ * it is already published on mainnet. Use `ReserveAssetDataEventV2` instead, which carries
1760
+ * every field here plus `conf`.
1761
+ */
1757
1762
  export class ReserveAssetDataEvent {
1758
1763
  __StructClass = true;
1759
1764
  static get $typeName() {
@@ -1981,6 +1986,246 @@ export class ReserveAssetDataEvent {
1981
1986
  return ReserveAssetDataEvent.fromBcs(object.content);
1982
1987
  }
1983
1988
  }
1989
+ /* ============================== ReserveAssetDataEventV2 =============================== */
1990
+ export function isReserveAssetDataEventV2(type) {
1991
+ type = compressSuiType(type);
1992
+ return type
1993
+ === `${getTypeOrigin('suilend', 'reserve::ReserveAssetDataEventV2')}::reserve::ReserveAssetDataEventV2`;
1994
+ }
1995
+ export class ReserveAssetDataEventV2 {
1996
+ __StructClass = true;
1997
+ static get $typeName() {
1998
+ return `${getTypeOrigin('suilend', 'reserve::ReserveAssetDataEventV2')}::reserve::ReserveAssetDataEventV2`;
1999
+ }
2000
+ static $numTypeParams = 0;
2001
+ static $isPhantom = [];
2002
+ $typeName = ReserveAssetDataEventV2.$typeName;
2003
+ $fullTypeName;
2004
+ $typeArgs;
2005
+ $isPhantom = ReserveAssetDataEventV2.$isPhantom;
2006
+ lendingMarketId;
2007
+ coinType;
2008
+ reserveId;
2009
+ availableAmount;
2010
+ supplyAmount;
2011
+ borrowedAmount;
2012
+ availableAmountUsdEstimate;
2013
+ supplyAmountUsdEstimate;
2014
+ borrowedAmountUsdEstimate;
2015
+ borrowApr;
2016
+ supplyApr;
2017
+ ctokenSupply;
2018
+ cumulativeBorrowRate;
2019
+ price;
2020
+ smoothedPrice;
2021
+ priceLastUpdateTimestampS;
2022
+ conf;
2023
+ constructor(typeArgs, fields) {
2024
+ this.$fullTypeName = composeSuiType(ReserveAssetDataEventV2.$typeName, ...typeArgs);
2025
+ this.$typeArgs = typeArgs;
2026
+ this.lendingMarketId = fields.lendingMarketId;
2027
+ this.coinType = fields.coinType;
2028
+ this.reserveId = fields.reserveId;
2029
+ this.availableAmount = fields.availableAmount;
2030
+ this.supplyAmount = fields.supplyAmount;
2031
+ this.borrowedAmount = fields.borrowedAmount;
2032
+ this.availableAmountUsdEstimate = fields.availableAmountUsdEstimate;
2033
+ this.supplyAmountUsdEstimate = fields.supplyAmountUsdEstimate;
2034
+ this.borrowedAmountUsdEstimate = fields.borrowedAmountUsdEstimate;
2035
+ this.borrowApr = fields.borrowApr;
2036
+ this.supplyApr = fields.supplyApr;
2037
+ this.ctokenSupply = fields.ctokenSupply;
2038
+ this.cumulativeBorrowRate = fields.cumulativeBorrowRate;
2039
+ this.price = fields.price;
2040
+ this.smoothedPrice = fields.smoothedPrice;
2041
+ this.priceLastUpdateTimestampS = fields.priceLastUpdateTimestampS;
2042
+ this.conf = fields.conf;
2043
+ }
2044
+ static reified() {
2045
+ const reifiedBcs = ReserveAssetDataEventV2.bcs;
2046
+ return {
2047
+ get typeName() {
2048
+ return ReserveAssetDataEventV2.$typeName;
2049
+ },
2050
+ get fullTypeName() {
2051
+ return composeSuiType(ReserveAssetDataEventV2.$typeName, ...[]);
2052
+ },
2053
+ typeArgs: [],
2054
+ isPhantom: ReserveAssetDataEventV2.$isPhantom,
2055
+ reifiedTypeArgs: [],
2056
+ fromFields: (fields) => ReserveAssetDataEventV2.fromFields(fields),
2057
+ fromFieldsWithTypes: (item) => ReserveAssetDataEventV2.fromFieldsWithTypes(item),
2058
+ fromBcs: (data) => ReserveAssetDataEventV2.fromFields(reifiedBcs.parse(data)),
2059
+ bcs: reifiedBcs,
2060
+ fromJSONField: (field) => ReserveAssetDataEventV2.fromJSONField(field),
2061
+ fromJSON: (json) => ReserveAssetDataEventV2.fromJSON(json),
2062
+ fromCoreObject: (obj) => ReserveAssetDataEventV2.fromCoreObject(obj),
2063
+ fetch: async (client, id) => ReserveAssetDataEventV2.fetch(client, id),
2064
+ new: (fields) => {
2065
+ return new ReserveAssetDataEventV2([], fields);
2066
+ },
2067
+ kind: 'StructClassReified',
2068
+ };
2069
+ }
2070
+ static get r() {
2071
+ return ReserveAssetDataEventV2.reified();
2072
+ }
2073
+ static phantom() {
2074
+ return phantom(ReserveAssetDataEventV2.reified());
2075
+ }
2076
+ static get p() {
2077
+ return ReserveAssetDataEventV2.phantom();
2078
+ }
2079
+ static instantiateBcs() {
2080
+ return bcs.struct('ReserveAssetDataEventV2', {
2081
+ lending_market_id: bcs.bytes(32).transform({
2082
+ input: (val) => fromHex(val),
2083
+ output: (val) => toHex(val),
2084
+ }),
2085
+ coin_type: TypeName.bcs,
2086
+ reserve_id: bcs.bytes(32).transform({
2087
+ input: (val) => fromHex(val),
2088
+ output: (val) => toHex(val),
2089
+ }),
2090
+ available_amount: Decimal.bcs,
2091
+ supply_amount: Decimal.bcs,
2092
+ borrowed_amount: Decimal.bcs,
2093
+ available_amount_usd_estimate: Decimal.bcs,
2094
+ supply_amount_usd_estimate: Decimal.bcs,
2095
+ borrowed_amount_usd_estimate: Decimal.bcs,
2096
+ borrow_apr: Decimal.bcs,
2097
+ supply_apr: Decimal.bcs,
2098
+ ctoken_supply: bcs.u64(),
2099
+ cumulative_borrow_rate: Decimal.bcs,
2100
+ price: Decimal.bcs,
2101
+ smoothed_price: Decimal.bcs,
2102
+ price_last_update_timestamp_s: bcs.u64(),
2103
+ conf: Decimal.bcs,
2104
+ });
2105
+ }
2106
+ static cachedBcs = null;
2107
+ static get bcs() {
2108
+ if (!ReserveAssetDataEventV2.cachedBcs) {
2109
+ ReserveAssetDataEventV2.cachedBcs = ReserveAssetDataEventV2.instantiateBcs();
2110
+ }
2111
+ return ReserveAssetDataEventV2.cachedBcs;
2112
+ }
2113
+ static fromFields(fields) {
2114
+ return ReserveAssetDataEventV2.reified().new({
2115
+ lendingMarketId: decodeFromFields('address', fields.lending_market_id),
2116
+ coinType: decodeFromFields(TypeName.reified(), fields.coin_type),
2117
+ reserveId: decodeFromFields('address', fields.reserve_id),
2118
+ availableAmount: decodeFromFields(Decimal.reified(), fields.available_amount),
2119
+ supplyAmount: decodeFromFields(Decimal.reified(), fields.supply_amount),
2120
+ borrowedAmount: decodeFromFields(Decimal.reified(), fields.borrowed_amount),
2121
+ availableAmountUsdEstimate: decodeFromFields(Decimal.reified(), fields.available_amount_usd_estimate),
2122
+ supplyAmountUsdEstimate: decodeFromFields(Decimal.reified(), fields.supply_amount_usd_estimate),
2123
+ borrowedAmountUsdEstimate: decodeFromFields(Decimal.reified(), fields.borrowed_amount_usd_estimate),
2124
+ borrowApr: decodeFromFields(Decimal.reified(), fields.borrow_apr),
2125
+ supplyApr: decodeFromFields(Decimal.reified(), fields.supply_apr),
2126
+ ctokenSupply: decodeFromFields('u64', fields.ctoken_supply),
2127
+ cumulativeBorrowRate: decodeFromFields(Decimal.reified(), fields.cumulative_borrow_rate),
2128
+ price: decodeFromFields(Decimal.reified(), fields.price),
2129
+ smoothedPrice: decodeFromFields(Decimal.reified(), fields.smoothed_price),
2130
+ priceLastUpdateTimestampS: decodeFromFields('u64', fields.price_last_update_timestamp_s),
2131
+ conf: decodeFromFields(Decimal.reified(), fields.conf),
2132
+ });
2133
+ }
2134
+ static fromFieldsWithTypes(item) {
2135
+ if (!isReserveAssetDataEventV2(item.type)) {
2136
+ throw new Error('not a ReserveAssetDataEventV2 type');
2137
+ }
2138
+ return ReserveAssetDataEventV2.reified().new({
2139
+ lendingMarketId: decodeFromFieldsWithTypes('address', item.fields.lending_market_id),
2140
+ coinType: decodeFromFieldsWithTypes(TypeName.reified(), item.fields.coin_type),
2141
+ reserveId: decodeFromFieldsWithTypes('address', item.fields.reserve_id),
2142
+ availableAmount: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.available_amount),
2143
+ supplyAmount: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.supply_amount),
2144
+ borrowedAmount: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.borrowed_amount),
2145
+ availableAmountUsdEstimate: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.available_amount_usd_estimate),
2146
+ supplyAmountUsdEstimate: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.supply_amount_usd_estimate),
2147
+ borrowedAmountUsdEstimate: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.borrowed_amount_usd_estimate),
2148
+ borrowApr: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.borrow_apr),
2149
+ supplyApr: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.supply_apr),
2150
+ ctokenSupply: decodeFromFieldsWithTypes('u64', item.fields.ctoken_supply),
2151
+ cumulativeBorrowRate: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.cumulative_borrow_rate),
2152
+ price: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.price),
2153
+ smoothedPrice: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.smoothed_price),
2154
+ priceLastUpdateTimestampS: decodeFromFieldsWithTypes('u64', item.fields.price_last_update_timestamp_s),
2155
+ conf: decodeFromFieldsWithTypes(Decimal.reified(), item.fields.conf),
2156
+ });
2157
+ }
2158
+ static fromBcs(data) {
2159
+ return ReserveAssetDataEventV2.fromFields(ReserveAssetDataEventV2.bcs.parse(data));
2160
+ }
2161
+ toJSONField() {
2162
+ return {
2163
+ lendingMarketId: this.lendingMarketId,
2164
+ coinType: this.coinType,
2165
+ reserveId: this.reserveId,
2166
+ availableAmount: this.availableAmount.toJSONField(),
2167
+ supplyAmount: this.supplyAmount.toJSONField(),
2168
+ borrowedAmount: this.borrowedAmount.toJSONField(),
2169
+ availableAmountUsdEstimate: this.availableAmountUsdEstimate.toJSONField(),
2170
+ supplyAmountUsdEstimate: this.supplyAmountUsdEstimate.toJSONField(),
2171
+ borrowedAmountUsdEstimate: this.borrowedAmountUsdEstimate.toJSONField(),
2172
+ borrowApr: this.borrowApr.toJSONField(),
2173
+ supplyApr: this.supplyApr.toJSONField(),
2174
+ ctokenSupply: this.ctokenSupply.toString(),
2175
+ cumulativeBorrowRate: this.cumulativeBorrowRate.toJSONField(),
2176
+ price: this.price.toJSONField(),
2177
+ smoothedPrice: this.smoothedPrice.toJSONField(),
2178
+ priceLastUpdateTimestampS: this.priceLastUpdateTimestampS.toString(),
2179
+ conf: this.conf.toJSONField(),
2180
+ };
2181
+ }
2182
+ toJSON() {
2183
+ return { $typeName: this.$typeName, $typeArgs: this.$typeArgs, ...this.toJSONField() };
2184
+ }
2185
+ static fromJSONField(field) {
2186
+ return ReserveAssetDataEventV2.reified().new({
2187
+ lendingMarketId: decodeFromJSONField('address', field.lendingMarketId),
2188
+ coinType: decodeFromJSONField(TypeName.reified(), field.coinType),
2189
+ reserveId: decodeFromJSONField('address', field.reserveId),
2190
+ availableAmount: decodeFromJSONField(Decimal.reified(), field.availableAmount),
2191
+ supplyAmount: decodeFromJSONField(Decimal.reified(), field.supplyAmount),
2192
+ borrowedAmount: decodeFromJSONField(Decimal.reified(), field.borrowedAmount),
2193
+ availableAmountUsdEstimate: decodeFromJSONField(Decimal.reified(), field.availableAmountUsdEstimate),
2194
+ supplyAmountUsdEstimate: decodeFromJSONField(Decimal.reified(), field.supplyAmountUsdEstimate),
2195
+ borrowedAmountUsdEstimate: decodeFromJSONField(Decimal.reified(), field.borrowedAmountUsdEstimate),
2196
+ borrowApr: decodeFromJSONField(Decimal.reified(), field.borrowApr),
2197
+ supplyApr: decodeFromJSONField(Decimal.reified(), field.supplyApr),
2198
+ ctokenSupply: decodeFromJSONField('u64', field.ctokenSupply),
2199
+ cumulativeBorrowRate: decodeFromJSONField(Decimal.reified(), field.cumulativeBorrowRate),
2200
+ price: decodeFromJSONField(Decimal.reified(), field.price),
2201
+ smoothedPrice: decodeFromJSONField(Decimal.reified(), field.smoothedPrice),
2202
+ priceLastUpdateTimestampS: decodeFromJSONField('u64', field.priceLastUpdateTimestampS),
2203
+ conf: decodeFromJSONField(Decimal.reified(), field.conf),
2204
+ });
2205
+ }
2206
+ static fromJSON(json) {
2207
+ if (json.$typeName !== ReserveAssetDataEventV2.$typeName) {
2208
+ throw new Error(`not a ReserveAssetDataEventV2 json object: expected '${ReserveAssetDataEventV2.$typeName}' but got '${json.$typeName}'`);
2209
+ }
2210
+ return ReserveAssetDataEventV2.fromJSONField(json);
2211
+ }
2212
+ static fromCoreObject(obj) {
2213
+ if (!isReserveAssetDataEventV2(obj.type)) {
2214
+ throw new Error(`object at ${obj.objectId} is not a ReserveAssetDataEventV2 object`);
2215
+ }
2216
+ return ReserveAssetDataEventV2.fromBcs(obj.content);
2217
+ }
2218
+ static async fetch(client, id) {
2219
+ const { object } = await client.core.getObject({
2220
+ objectId: id,
2221
+ include: { content: true },
2222
+ });
2223
+ if (!isReserveAssetDataEventV2(object.type)) {
2224
+ throw new Error(`object at id ${id} is not a ReserveAssetDataEventV2 object`);
2225
+ }
2226
+ return ReserveAssetDataEventV2.fromBcs(object.content);
2227
+ }
2228
+ }
1984
2229
  /* ============================== ClaimStakingRewardsEvent =============================== */
1985
2230
  export function isClaimStakingRewardsEvent(type) {
1986
2231
  type = compressSuiType(type);
package/client.d.ts CHANGED
@@ -19,10 +19,12 @@ export interface PriceUpdate {
19
19
  }
20
20
  export declare function needsPriceRefresh(stalenessSeconds: number): boolean;
21
21
  export declare const ADMIN_ADDRESS = "0xb1ffbc2e1915f44b8f271a703becc1bf8aa79bc22431a58900a102892b783c25";
22
+ export declare function getStrategyWrapperPackageId(): string;
23
+ export declare function setStrategyWrapperPackageId(packageId: string): void;
22
24
  export declare const LENDING_MARKET_REGISTRY_ID = "0x64faff8d91a56c4f55debbb44767b009ee744a70bc2cc8e3bbd2718c92f85931";
23
25
  export declare const LENDING_MARKET_ID: string, LENDING_MARKET_TYPE: string;
24
26
  export declare const STEAMM_LM_LENDING_MARKET_ID: string, STEAMM_LM_LENDING_MARKET_TYPE: string;
25
- export declare function getLatestPackageId(suiGrpcClient: SuiGrpcClient, upgradeCapId: string): Promise<any>;
27
+ export declare function getLatestPackageId(suiGrpcClient: SuiGrpcClient, upgradeCapId: string): Promise<string>;
26
28
  /**
27
29
  * Lists every owned object of `type`, following pagination.
28
30
  *
@@ -84,6 +86,12 @@ export declare class SuilendClient {
84
86
  id: string;
85
87
  type: string;
86
88
  }[], suiGrpcClient: SuiGrpcClient, logPackageId?: boolean): Promise<SuilendClient[]>;
89
+ /**
90
+ * Sets only the suilend package, to `publishedAt`, and leaves the
91
+ * strategy_wrapper package as it was. Callers that build strategy
92
+ * transactions must also call `setStrategyWrapperPackageId` with the
93
+ * strategy_wrapper package for MAIN's lending market version.
94
+ */
87
95
  static initializeAllFromObjects(lendingMarkets: {
88
96
  id: string;
89
97
  type: string;
@@ -94,6 +102,8 @@ export declare class SuilendClient {
94
102
  }>;
95
103
  /** A reserve's confidence multiplier `k`, in bps; pass `parsedReserve.config.additionalFields.id`. 0 when unset. */
96
104
  static getReserveConfidenceMultiplierBps(suiGrpcClient: SuiGrpcClient, additionalFieldsBagId: string): Promise<BigNumber>;
105
+ /** 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
+ static getReserveStoredConfidence(suiGrpcClient: SuiGrpcClient, reserveId: string): Promise<BigNumber>;
97
107
  static createNewLendingMarket(registryId: string, lendingMarketType: string, transaction: Transaction): {
98
108
  NestedResult: [number, number];
99
109
  $kind: "NestedResult";
package/client.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { bcs } from "@mysten/sui/bcs";
2
- import { SUI_CLOCK_OBJECT_ID, SUI_SYSTEM_STATE_OBJECT_ID, isValidSuiAddress, normalizeStructTag, normalizeSuiObjectId, toHex, } from "@mysten/sui/utils";
2
+ import { SUI_CLOCK_OBJECT_ID, SUI_SYSTEM_STATE_OBJECT_ID, isValidSuiAddress, normalizeStructTag, normalizeSuiAddress, normalizeSuiObjectId, toHex, } from "@mysten/sui/utils";
3
3
  import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
4
4
  import BigNumber from "bignumber.js";
5
5
  import { extractCTokenCoinType, getAllCoins, getSpendableCoin, } from "@suilend/sui-core";
6
6
  import { phantom } from "./_generated/_framework/reified.js";
7
+ import { Decimal } from "./_generated/suilend/decimal/structs.js";
8
+ import { decimalToBigNumber } from "./utils/simulate.js";
7
9
  import { PKG_V10, setPublishedAt } from "./_generated/suilend/index.js";
8
10
  import { getPublishedAt } from "./_generated/_envs/index.js";
9
11
  import { PACKAGE_ID } from "./_generated/suilend/index.js";
@@ -58,6 +60,20 @@ const PUBLISHED_AT_BY_MARKET_VERSION = new Map([
58
60
  "0x59672975e15c58ffc9450f5236b6aa9fa2407d94b8081e634778aa01957d8c6f",
59
61
  ],
60
62
  ]);
63
+ const STRATEGY_WRAPPER_UPGRADE_CAP_ID = "0x486ef016bd357fadf981aba35a6c31df8d4c0c4136b2e78fdda87cb2832f3033";
64
+ const STRATEGY_WRAPPER_PACKAGE_ID_V7 = "0x864b66441e95323c320ee7584592769930a2d236b45d731011ee7a98eb785b35";
65
+ const STRATEGY_WRAPPER_PACKAGE_ID_BY_MARKET_VERSION = new Map([
66
+ [BigInt(7), STRATEGY_WRAPPER_PACKAGE_ID_V7],
67
+ ]);
68
+ let strategyWrapperPackage = STRATEGY_WRAPPER_PACKAGE_ID_V7;
69
+ export function getStrategyWrapperPackageId() {
70
+ if (typeof strategyWrapperPackage !== "string")
71
+ throw new Error(`The strategy_wrapper package is unresolved: reading its UpgradeCap ${STRATEGY_WRAPPER_UPGRADE_CAP_ID} failed at MAIN lending market version ${LATEST_MARKET_VERSION}. Retry SuilendClient.initialize before building strategy transactions.`, { cause: strategyWrapperPackage.readError });
72
+ return strategyWrapperPackage;
73
+ }
74
+ export function setStrategyWrapperPackageId(packageId) {
75
+ strategyWrapperPackage = packageId;
76
+ }
61
77
  export const LENDING_MARKET_REGISTRY_ID = "0x64faff8d91a56c4f55debbb44767b009ee744a70bc2cc8e3bbd2718c92f85931";
62
78
  export const [LENDING_MARKET_ID, LENDING_MARKET_TYPE] = [
63
79
  "0x84030d26d85eaa7035084a057f2f11f701b7e2e4eda87551becbc7c97505ece1",
@@ -84,7 +100,12 @@ export async function getLatestPackageId(suiGrpcClient, upgradeCapId) {
84
100
  objectId: upgradeCapId,
85
101
  include: { json: true },
86
102
  })
87
- .then(({ object }) => object.json.package)
103
+ .then(({ object }) => {
104
+ const packageId = object.json?.package;
105
+ if (typeof packageId !== "string" || !isValidSuiAddress(packageId))
106
+ throw new Error(`UpgradeCap ${upgradeCapId} does not name a valid package id (got ${String(packageId)})`);
107
+ return normalizeSuiAddress(packageId);
108
+ })
88
109
  .finally(() => latestPackageIdCache.delete(upgradeCapId));
89
110
  latestPackageIdCache.set(upgradeCapId, promise);
90
111
  return promise;
@@ -244,13 +265,27 @@ function startLatestPackageIdRead(suiGrpcClient) {
244
265
  latestPackageId.catch(() => { });
245
266
  return latestPackageId;
246
267
  }
247
- async function publishedAtForMainVersion(mainVersion, latestPackageId) {
248
- if (mainVersion === LATEST_MARKET_VERSION)
249
- return latestPackageId;
250
- const pinned = PUBLISHED_AT_BY_MARKET_VERSION.get(mainVersion);
251
- if (!pinned)
252
- throw new Error(`No suilend package is known for lending market version ${mainVersion} (MAIN ${LENDING_MARKET_ID})`);
253
- return pinned;
268
+ async function applyPackagesForMainVersion(suiGrpcClient, mainVersion, latestPackageId, logPackageId) {
269
+ if (mainVersion === LATEST_MARKET_VERSION) {
270
+ const [publishedAt, strategyWrapper] = await Promise.all([
271
+ latestPackageId,
272
+ getLatestPackageId(suiGrpcClient, STRATEGY_WRAPPER_UPGRADE_CAP_ID).catch((readError) => ({ readError })),
273
+ ]);
274
+ applyPublishedAt(publishedAt, logPackageId);
275
+ strategyWrapperPackage = strategyWrapper;
276
+ return;
277
+ }
278
+ const publishedAt = PUBLISHED_AT_BY_MARKET_VERSION.get(mainVersion);
279
+ const strategyWrapper = STRATEGY_WRAPPER_PACKAGE_ID_BY_MARKET_VERSION.get(mainVersion);
280
+ if (!publishedAt || !strategyWrapper) {
281
+ const unknown = [
282
+ ...(publishedAt ? [] : ["suilend"]),
283
+ ...(strategyWrapper ? [] : ["strategy_wrapper"]),
284
+ ];
285
+ throw new Error(`No ${unknown.join(" or ")} package is known for lending market version ${mainVersion} (MAIN ${LENDING_MARKET_ID})`);
286
+ }
287
+ applyPublishedAt(publishedAt, logPackageId);
288
+ strategyWrapperPackage = strategyWrapper;
254
289
  }
255
290
  async function readMainVersion(suiGrpcClient) {
256
291
  const { object } = await suiGrpcClient.getObject({
@@ -368,7 +403,7 @@ export class SuilendClient {
368
403
  const mainVersion = fetchedMainVersion ?? lendingMarket.version;
369
404
  if (lendingMarket.version !== mainVersion)
370
405
  throw new Error(versionMismatch(lendingMarketId, lendingMarket.version, mainVersion));
371
- applyPublishedAt(await publishedAtForMainVersion(mainVersion, latestPackageId), logPackageId);
406
+ await applyPackagesForMainVersion(suiGrpcClient, mainVersion, latestPackageId, logPackageId);
372
407
  return new SuilendClient(lendingMarket, suiGrpcClient);
373
408
  }
374
409
  /**
@@ -396,12 +431,18 @@ export class SuilendClient {
396
431
  const mainVersion = fetchedMainVersion ??
397
432
  clients[lendingMarkets.findIndex(({ id }) => isMainMarket(id))]
398
433
  .lendingMarket.version;
399
- applyPublishedAt(await publishedAtForMainVersion(mainVersion, latestPackageId), logPackageId);
434
+ await applyPackagesForMainVersion(suiGrpcClient, mainVersion, latestPackageId, logPackageId);
400
435
  for (const { lendingMarket } of clients)
401
436
  if (lendingMarket.version !== mainVersion)
402
437
  console.warn(`@suilend/sdk | ${versionMismatch(lendingMarket.id, lendingMarket.version, mainVersion)}`);
403
438
  return clients;
404
439
  }
440
+ /**
441
+ * Sets only the suilend package, to `publishedAt`, and leaves the
442
+ * strategy_wrapper package as it was. Callers that build strategy
443
+ * transactions must also call `setStrategyWrapperPackageId` with the
444
+ * strategy_wrapper package for MAIN's lending market version.
445
+ */
405
446
  static initializeAllFromObjects(lendingMarkets, objects, publishedAt, suiGrpcClient, logPackageId) {
406
447
  if (!isValidSuiAddress(publishedAt))
407
448
  throw new Error(`publishedAt ${publishedAt} is not a Sui package id`);
@@ -426,6 +467,17 @@ export class SuilendClient {
426
467
  });
427
468
  return new BigNumber(bcs.u64().parse(dynamicField.value.bcs));
428
469
  }
470
+ /** 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. */
471
+ static async getReserveStoredConfidence(suiGrpcClient, reserveId) {
472
+ const match = await findBagEntryByTypeSuffix(suiGrpcClient, reserveId, "::reserve::ConfidenceKey");
473
+ if (!match)
474
+ return new BigNumber(0);
475
+ const { dynamicField } = await suiGrpcClient.getDynamicField({
476
+ parentId: reserveId,
477
+ name: match.name,
478
+ });
479
+ return decimalToBigNumber(Decimal.fromBcs(dynamicField.value.bcs));
480
+ }
429
481
  static createNewLendingMarket(registryId, lendingMarketType, transaction) {
430
482
  const [ownerCap, lendingMarket] = createLendingMarket(transaction, lendingMarketType, transaction.object(registryId));
431
483
  transaction.moveCall({
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
  };
@@ -2,10 +2,9 @@ import { SUI_CLOCK_OBJECT_ID, SUI_SYSTEM_STATE_OBJECT_ID, } from "@mysten/sui/ut
2
2
  import BigNumber from "bignumber.js";
3
3
  import BN from "bn.js";
4
4
  import { MAX_U64, NORMALIZED_AUSD_COINTYPE, NORMALIZED_SUI_COINTYPE, NORMALIZED_USDC_COINTYPE, NORMALIZED_USDsui_COINTYPE, NORMALIZED_eEARN_COINTYPE, NORMALIZED_sSUI_COINTYPE, NORMALIZED_stratSUI_COINTYPE, NORMALIZED_suiUSDT_COINTYPE, NORMALIZED_suiWBTC_COINTYPE, NORMALIZED_xBTC_COINTYPE, isSui, } from "@suilend/sui-core";
5
- import { LENDING_MARKET_ID, LENDING_MARKET_TYPE, } from "../client.js";
5
+ import { getStrategyWrapperPackageId, LENDING_MARKET_ID, LENDING_MARKET_TYPE, } from "../client.js";
6
6
  import { Side } from "./types.js";
7
7
  export const STRATEGY_WRAPPER_PACKAGE_ID_V1 = "0xba97dc73a07638d03d77ad2161484eb21db577edc9cadcd7035fef4b4f2f6fa1";
8
- const STRATEGY_WRAPPER_PACKAGE_ID_V7 = "0x864b66441e95323c320ee7584592769930a2d236b45d731011ee7a98eb785b35";
9
8
  export var StrategyType;
10
9
  (function (StrategyType) {
11
10
  StrategyType["sSUI_SUI_LOOPING"] = "1";
@@ -242,7 +241,7 @@ const getStrategyLendingMarket = (strategyType) => {
242
241
  export const strategyDeposit = (strategyType, coin, coinType, strategyOwnerCap, reserveArrayIndex, transaction) => {
243
242
  const { lendingMarketId, lendingMarketType } = getStrategyLendingMarket(strategyType);
244
243
  return transaction.moveCall({
245
- target: `${STRATEGY_WRAPPER_PACKAGE_ID_V7}::strategy_wrapper::deposit_liquidity_and_deposit_into_obligation`,
244
+ target: `${getStrategyWrapperPackageId()}::strategy_wrapper::deposit_liquidity_and_deposit_into_obligation`,
246
245
  typeArguments: [lendingMarketType, coinType],
247
246
  arguments: [
248
247
  transaction.object(strategyOwnerCap),
@@ -257,7 +256,7 @@ export const strategyBorrow = (strategyType, coinType, strategyOwnerCap, reserve
257
256
  const { lendingMarketId, lendingMarketType } = getStrategyLendingMarket(strategyType);
258
257
  return isSui(coinType)
259
258
  ? transaction.moveCall({
260
- target: `${STRATEGY_WRAPPER_PACKAGE_ID_V7}::strategy_wrapper::borrow_sui_from_obligation`,
259
+ target: `${getStrategyWrapperPackageId()}::strategy_wrapper::borrow_sui_from_obligation`,
261
260
  typeArguments: [lendingMarketType],
262
261
  arguments: [
263
262
  transaction.object(strategyOwnerCap),
@@ -269,7 +268,7 @@ export const strategyBorrow = (strategyType, coinType, strategyOwnerCap, reserve
269
268
  ],
270
269
  })
271
270
  : transaction.moveCall({
272
- target: `${STRATEGY_WRAPPER_PACKAGE_ID_V7}::strategy_wrapper::borrow_from_obligation`,
271
+ target: `${getStrategyWrapperPackageId()}::strategy_wrapper::borrow_from_obligation`,
273
272
  typeArguments: [lendingMarketType, coinType],
274
273
  arguments: [
275
274
  transaction.object(strategyOwnerCap),
@@ -283,7 +282,7 @@ export const strategyBorrow = (strategyType, coinType, strategyOwnerCap, reserve
283
282
  export const strategyWithdraw = (strategyType, coinType, strategyOwnerCap, reserveArrayIndex, value, transaction) => {
284
283
  const { lendingMarketId, lendingMarketType } = getStrategyLendingMarket(strategyType);
285
284
  return transaction.moveCall({
286
- target: `${STRATEGY_WRAPPER_PACKAGE_ID_V7}::strategy_wrapper::withdraw_from_obligation_and_redeem`,
285
+ target: `${getStrategyWrapperPackageId()}::strategy_wrapper::withdraw_from_obligation_and_redeem`,
287
286
  typeArguments: [lendingMarketType, coinType],
288
287
  arguments: [
289
288
  transaction.object(strategyOwnerCap),
@@ -297,7 +296,7 @@ export const strategyWithdraw = (strategyType, coinType, strategyOwnerCap, reser
297
296
  const strategyClaimRewards = (strategyType, coinType, strategyOwnerCap, reserveArrayIndex, rewardIndex, side, transaction) => {
298
297
  const { lendingMarketId, lendingMarketType } = getStrategyLendingMarket(strategyType);
299
298
  return transaction.moveCall({
300
- target: `${STRATEGY_WRAPPER_PACKAGE_ID_V7}::strategy_wrapper::claim_rewards`,
299
+ target: `${getStrategyWrapperPackageId()}::strategy_wrapper::claim_rewards`,
301
300
  typeArguments: [lendingMarketType, coinType],
302
301
  arguments: [
303
302
  transaction.object(strategyOwnerCap),
@@ -432,7 +431,7 @@ export const createStrategyOwnerCapIfNoneExists = (strategyType, strategyOwnerCa
432
431
  strategyOwnerCapId = strategyOwnerCap.id;
433
432
  else {
434
433
  strategyOwnerCapId = transaction.moveCall({
435
- target: `${STRATEGY_WRAPPER_PACKAGE_ID_V7}::strategy_wrapper::create_strategy_owner_cap`,
434
+ target: `${getStrategyWrapperPackageId()}::strategy_wrapper::create_strategy_owner_cap`,
436
435
  typeArguments: [lendingMarketType],
437
436
  arguments: [
438
437
  transaction.object(lendingMarketId),
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@suilend/sdk","version":"13.0.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/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);
package/utils/events.d.ts CHANGED
@@ -69,6 +69,26 @@ export declare class ReserveAssetDataEvent extends TypedParamsSuiEvent<{
69
69
  price_last_update_timestamp_s: u64;
70
70
  }> {
71
71
  }
72
+ export declare class ReserveAssetDataEventV2 extends TypedParamsSuiEvent<{
73
+ lending_market_id: address;
74
+ coin_type: TypeName;
75
+ 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;
84
+ ctoken_supply: u64;
85
+ cumulative_borrow_rate: Decimal;
86
+ price: Decimal;
87
+ smoothed_price: Decimal;
88
+ price_last_update_timestamp_s: u64;
89
+ conf: Decimal;
90
+ }> {
91
+ }
72
92
  export declare class MintEvent extends TypedParamsSuiEvent<{
73
93
  lending_market_id: address;
74
94
  coin_type: TypeName;
package/utils/events.js CHANGED
@@ -26,7 +26,7 @@ class TypedParamsSuiEvent {
26
26
  return this.event.json;
27
27
  }
28
28
  isType(module, eventType) {
29
- return this.event.eventType.includes(`${module}::${eventType}`);
29
+ return this.event.eventType.endsWith(`${module}::${eventType}`);
30
30
  }
31
31
  }
32
32
  export class GenericSuilendEvent extends TypedParamsSuiEvent {
@@ -35,6 +35,8 @@ export class InterestUpdateEvent extends TypedParamsSuiEvent {
35
35
  }
36
36
  export class ReserveAssetDataEvent extends TypedParamsSuiEvent {
37
37
  }
38
+ export class ReserveAssetDataEventV2 extends TypedParamsSuiEvent {
39
+ }
38
40
  export class MintEvent extends TypedParamsSuiEvent {
39
41
  }
40
42
  export class RedeemEvent extends TypedParamsSuiEvent {
@@ -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,13 +147,28 @@ 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;
151
157
  export declare const decimalToBigNumber: (value: Decimal) => BigNumber;
158
+ /**
159
+ * Mirrors reserve.move's `price_lower_bound`/`price_upper_bound`: the one
160
+ * off-chain place this formula lives. `conf` and `kBps` are the reserve's
161
+ * stored Pyth confidence and its `ReserveConfig` confidence multiplier (in
162
+ * bps, e.g. 30000 for a logical k=3) -- both plain human-scale BigNumbers,
163
+ * not WAD-scaled Decimals. `kBps=0` disables the margin entirely: both
164
+ * bounds collapse to plain `min`/`max(price, smoothedPrice)`.
165
+ */
166
+ export declare const applyConfidenceMargin: (price: BigNumber, smoothedPrice: BigNumber, conf: BigNumber, kBps: BigNumber) => {
167
+ lowerBound: BigNumber;
168
+ upperBound: BigNumber;
169
+ };
152
170
  export declare const getCTokenMarketValue: (reserve: Reserve<string>, depositedCTokenAmount: BigNumber) => BigNumber;
153
- 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;
154
172
  export declare const cTokenRatio: (reserve: Reserve<string>) => BigNumber;
155
173
  export declare const totalSupply: (reserve: Reserve<string>) => BigNumber;
156
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
@@ -441,16 +474,38 @@ export const stringToDecimal = (value) => {
441
474
  export const decimalToBigNumber = (value) => {
442
475
  return new BigNumber(value.value.toString()).div(WAD);
443
476
  };
477
+ /**
478
+ * Mirrors reserve.move's `price_lower_bound`/`price_upper_bound`: the one
479
+ * off-chain place this formula lives. `conf` and `kBps` are the reserve's
480
+ * stored Pyth confidence and its `ReserveConfig` confidence multiplier (in
481
+ * bps, e.g. 30000 for a logical k=3) -- both plain human-scale BigNumbers,
482
+ * not WAD-scaled Decimals. `kBps=0` disables the margin entirely: both
483
+ * bounds collapse to plain `min`/`max(price, smoothedPrice)`.
484
+ */
485
+ export const applyConfidenceMargin = (price, smoothedPrice, conf, kBps) => {
486
+ const margin = kBps.dividedBy(10_000).multipliedBy(conf);
487
+ const lowerBound = BigNumber.max(BigNumber.min(price, smoothedPrice).minus(margin), new BigNumber(0));
488
+ const upperBound = BigNumber.max(price, smoothedPrice).plus(margin);
489
+ return { lowerBound, upperBound };
490
+ };
444
491
  export const getCTokenMarketValue = (reserve, depositedCTokenAmount) => {
445
492
  const liquidityAmount = depositedCTokenAmount.multipliedBy(cTokenRatio(reserve));
446
493
  return decimalToBigNumber(reserve.price)
447
494
  .multipliedBy(liquidityAmount)
448
495
  .dividedBy(new BigNumber(10 ** reserve.mintDecimals));
449
496
  };
450
- 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) => {
451
502
  const liquidityAmount = depositedCTokenAmount.multipliedBy(cTokenRatio(reserve));
452
- const price = BigNumber.min(decimalToBigNumber(reserve.price), decimalToBigNumber(reserve.smoothedPrice));
453
- 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
454
509
  .multipliedBy(liquidityAmount)
455
510
  .dividedBy(new BigNumber(10 ** reserve.mintDecimals));
456
511
  };