@suilend/sdk 13.7.0-next.g7a9fc12 → 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.
- package/_generated/suilend/reserve/structs.d.ts +7 -1
- package/_generated/suilend/reserve/structs.js +15 -1
- package/client.d.ts +6 -0
- package/client.js +15 -0
- package/lib/types.d.ts +2 -0
- package/package.json +1 -1
- package/parsers/apiReserveAssetDataEvent.js +8 -1
- package/parsers/reserve.js +4 -6
- package/utils/events.d.ts +2 -0
- package/utils/simulate.d.ts +16 -6
- package/utils/simulate.js +21 -13
|
@@ -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";
|
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({
|
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.7.0-next.
|
|
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
|
|
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)
|
package/parsers/reserve.js
CHANGED
|
@@ -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
|
|
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
|
|
26
|
-
|
|
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
|
@@ -88,6 +88,8 @@ export declare class ReserveAssetDataEventV2 extends TypedParamsSuiEvent<{
|
|
|
88
88
|
smoothed_price: u256;
|
|
89
89
|
price_last_update_timestamp_s: u64;
|
|
90
90
|
conf: u256;
|
|
91
|
+
unclamped_price: u256;
|
|
92
|
+
unclamped_smoothed_price: u256;
|
|
91
93
|
}> {
|
|
92
94
|
}
|
|
93
95
|
export declare class MintEvent extends TypedParamsSuiEvent<{
|
package/utils/simulate.d.ts
CHANGED
|
@@ -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. `
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
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: (
|
|
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. `
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
*
|
|
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 = (
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const
|
|
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)
|
|
528
|
+
? applyConfidenceMargin(low, high, conf, kBps, unclampedSpot(reserve))
|
|
529
|
+
.lowerBound
|
|
522
530
|
: low;
|
|
523
531
|
return lowerBoundPrice
|
|
524
532
|
.multipliedBy(liquidityAmount)
|