@suilend/sdk 9.0.0 → 10.0.0
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/client.d.ts +14 -2
- package/client.js +23 -7
- package/lib/pyth.d.ts +61 -0
- package/lib/pyth.js +83 -0
- package/package.json +1 -1
package/client.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { SuiClientTypes } from "@mysten/sui/client";
|
|
2
2
|
import { SuiGrpcClient } from "@mysten/sui/grpc";
|
|
3
3
|
import { Transaction, TransactionObjectArgument, TransactionObjectInput } from "@mysten/sui/transactions";
|
|
4
|
-
import {
|
|
4
|
+
import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
|
|
5
5
|
import { LendingMarket, ObligationOwnerCap } from "./_generated/suilend/lending-market/structs";
|
|
6
6
|
import { Obligation } from "./_generated/suilend/obligation/structs";
|
|
7
7
|
import { NewConfigArgs as CreateRateLimiterConfigArgs } from "./_generated/suilend/rate-limiter/functions";
|
|
8
8
|
import { CreateReserveConfigArgs } from "./_generated/suilend/reserve-config/functions";
|
|
9
|
+
import { type PriceUpdateDataSource } from "./lib/pyth";
|
|
9
10
|
import { Side } from "./lib/types";
|
|
10
11
|
export declare const ADMIN_ADDRESS: string;
|
|
11
12
|
export declare const LENDING_MARKET_REGISTRY_ID: string;
|
|
@@ -43,7 +44,18 @@ export declare class SuilendClient {
|
|
|
43
44
|
lendingMarket: LendingMarket<string>;
|
|
44
45
|
suiGrpcClient: SuiGrpcClient;
|
|
45
46
|
pythClient: SuiPythClient;
|
|
46
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The source of the signed update this client puts ON-CHAIN.
|
|
49
|
+
*
|
|
50
|
+
* Typed as the one-method `PriceUpdateDataSource` rather than the concrete
|
|
51
|
+
* `SuiPriceServiceConnection` it used to be: a real connection still satisfies
|
|
52
|
+
* it structurally, and the narrower type is what lets a caller inject an
|
|
53
|
+
* authenticated or proxied source without reimplementing a pyth client. It
|
|
54
|
+
* stays a public, reassignable field because consumers already assign it
|
|
55
|
+
* directly — the indexer to reach its failover connection, the admin dialogs
|
|
56
|
+
* to read update data for a reserve change.
|
|
57
|
+
*/
|
|
58
|
+
pythConnection: PriceUpdateDataSource;
|
|
47
59
|
constructor(lendingMarket: LendingMarket<string>, suiGrpcClient: SuiGrpcClient);
|
|
48
60
|
static initialize(lendingMarketId: string, lendingMarketType: string, suiGrpcClient: SuiGrpcClient, logPackageId?: boolean): Promise<SuilendClient>;
|
|
49
61
|
/**
|
package/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SUI_CLOCK_OBJECT_ID, SUI_SYSTEM_STATE_OBJECT_ID, normalizeStructTag, normalizeSuiObjectId, toHex, } from "@mysten/sui/utils";
|
|
2
|
-
import {
|
|
2
|
+
import { SuiPythClient } from "@pythnetwork/pyth-sui-js";
|
|
3
3
|
import { extractCTokenCoinType, getAllCoins, getSpendableCoin, } from "@suilend/sui-core";
|
|
4
4
|
import { phantom } from "./_generated/_framework/reified.js";
|
|
5
5
|
import { PKG_V10, setPublishedAt } from "./_generated/suilend/index.js";
|
|
@@ -11,7 +11,7 @@ import { Obligation } from "./_generated/suilend/obligation/structs.js";
|
|
|
11
11
|
import { newConfig as createRateLimiterConfig, } from "./_generated/suilend/rate-limiter/functions.js";
|
|
12
12
|
import { createReserveConfig, } from "./_generated/suilend/reserve-config/functions.js";
|
|
13
13
|
import { addReserveProCompatible, addReserveV2ProCompatible, changeReservePriceFeedProCompatible, priceInfoPublishTime, refreshReservePriceProCompatible, } from "./lib/proCompatible.js";
|
|
14
|
-
import {
|
|
14
|
+
import { resolvePriceUpdateDataSource, } from "./lib/pyth.js";
|
|
15
15
|
import { Side } from "./lib/types.js";
|
|
16
16
|
import { chunkedMultiGet } from "./utils/obligation.js";
|
|
17
17
|
const SUI_COINTYPE = "0x2::sui::SUI";
|
|
@@ -144,6 +144,17 @@ export class SuilendClient {
|
|
|
144
144
|
lendingMarket;
|
|
145
145
|
suiGrpcClient;
|
|
146
146
|
pythClient;
|
|
147
|
+
/**
|
|
148
|
+
* The source of the signed update this client puts ON-CHAIN.
|
|
149
|
+
*
|
|
150
|
+
* Typed as the one-method `PriceUpdateDataSource` rather than the concrete
|
|
151
|
+
* `SuiPriceServiceConnection` it used to be: a real connection still satisfies
|
|
152
|
+
* it structurally, and the narrower type is what lets a caller inject an
|
|
153
|
+
* authenticated or proxied source without reimplementing a pyth client. It
|
|
154
|
+
* stays a public, reassignable field because consumers already assign it
|
|
155
|
+
* directly — the indexer to reach its failover connection, the admin dialogs
|
|
156
|
+
* to read update data for a reserve change.
|
|
157
|
+
*/
|
|
147
158
|
pythConnection;
|
|
148
159
|
constructor(lendingMarket, suiGrpcClient) {
|
|
149
160
|
this.lendingMarket = lendingMarket;
|
|
@@ -161,10 +172,13 @@ export class SuilendClient {
|
|
|
161
172
|
// deposit/withdraw/borrow/repay, and nothing read-only touches it, so a
|
|
162
173
|
// typecheck and every page-load check stay green while writes are broken.
|
|
163
174
|
this.pythClient = new SuiPythClient(suiGrpcClient, PYTH_STATE_ID, WORMHOLE_STATE_ID);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
175
|
+
// Deliberately NOT a public-Hermes connection, which is what stood here.
|
|
176
|
+
// `WORMHOLE_STATE_ID` above is unconditionally the pro-compatible
|
|
177
|
+
// deployment, and public Hermes signs with a guardian set that deployment
|
|
178
|
+
// does not hold — so that default could not produce a usable update for any
|
|
179
|
+
// feed, and only looked harmless because `refreshAll` skips the update
|
|
180
|
+
// entirely while a feed is fresh. See `resolvePriceUpdateDataSource`.
|
|
181
|
+
this.pythConnection = resolvePriceUpdateDataSource();
|
|
168
182
|
}
|
|
169
183
|
static async initialize(lendingMarketId, lendingMarketType, suiGrpcClient, logPackageId) {
|
|
170
184
|
const lendingMarket = await LendingMarket.fetch(suiGrpcClient, phantom(lendingMarketType), lendingMarketId);
|
|
@@ -488,8 +502,10 @@ export class SuilendClient {
|
|
|
488
502
|
});
|
|
489
503
|
const publishTime = priceInfoPublishTime(object.json, priceInfoObjectId);
|
|
490
504
|
const stalenessSeconds = Date.now() / 1000 - Number(publishTime);
|
|
505
|
+
// 20s, not MAX_STALENESS_SECONDS (60): the update has to leave the
|
|
506
|
+
// object fresh enough to still satisfy `refresh_reserve_price` after
|
|
507
|
+
// the transaction lands, not merely fresh at the moment it is read.
|
|
491
508
|
if (stalenessSeconds > 20) {
|
|
492
|
-
const reserve = this.lendingMarket.reserves[Number(reserveArrayIndexes[+i])];
|
|
493
509
|
stalePriceIdentifiers.push(priceIdentifiers[+i]);
|
|
494
510
|
}
|
|
495
511
|
})()));
|
package/lib/pyth.d.ts
CHANGED
|
@@ -106,3 +106,64 @@ export declare const hermesConnectionConfig: (hermesConfig?: HermesClientConfig)
|
|
|
106
106
|
* works without an injected connection.
|
|
107
107
|
*/
|
|
108
108
|
export declare const resolvePythConnection: (pythConnectionOverride?: PriceFeedSource, fallbackPythEndpoint?: string, hermesConfig?: HermesClientConfig) => Promise<PriceFeedSource>;
|
|
109
|
+
/**
|
|
110
|
+
* Where `SuilendClient` gets the signed price update it puts ON-CHAIN.
|
|
111
|
+
*
|
|
112
|
+
* Not the same thing as `PriceFeedSource`, and the distinction is the whole
|
|
113
|
+
* point of this type existing. `PriceFeedSource` answers "what is this feed
|
|
114
|
+
* worth" and is read off-chain; the answer is a number and any Hermes can
|
|
115
|
+
* produce it. This answers "give me a VAA the Pyth deployment our contracts
|
|
116
|
+
* link will verify" — a signed blob that a *specific* deployment's guardian set
|
|
117
|
+
* has to have signed. Injecting one has never affected the other, which is how
|
|
118
|
+
* an app could believe it had moved to Pyth Pro while every transaction it built
|
|
119
|
+
* still carried a public-Hermes VAA.
|
|
120
|
+
*
|
|
121
|
+
* One method, because that is all `SuilendClient` ever calls on the field.
|
|
122
|
+
*/
|
|
123
|
+
export interface PriceUpdateDataSource {
|
|
124
|
+
getPriceFeedsUpdateData(priceIds: string[]): Promise<Buffer[]>;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Register the process-wide source for on-chain price updates. Call at startup;
|
|
128
|
+
* clients constructed BEFORE the call still pick it up, because the SDK default
|
|
129
|
+
* resolves late (see `deferredPriceUpdateDataSource`).
|
|
130
|
+
*
|
|
131
|
+
* Process-wide rather than a constructor argument on purpose: consumers build a
|
|
132
|
+
* `SuilendClient` in many places (perpetual-ui alone has 17 `initialize` call
|
|
133
|
+
* sites across four apps), and a per-site argument means the site somebody adds
|
|
134
|
+
* next silently reverts to the broken path. One registration covers every
|
|
135
|
+
* instance, including ones constructed by code the caller does not own.
|
|
136
|
+
*
|
|
137
|
+
* Resolution order, most specific first:
|
|
138
|
+
* 1. `client.pythConnection = …` — a per-instance assignment always wins, and
|
|
139
|
+
* is how the indexer injects its authenticated failover connection.
|
|
140
|
+
* 2. whatever was registered here.
|
|
141
|
+
* 3. the SDK default.
|
|
142
|
+
*
|
|
143
|
+
* That order is load-bearing for the planned change to have the SDK resolve its
|
|
144
|
+
* own default endpoint: adding a real default at (3) cannot fight a consumer
|
|
145
|
+
* that registered at (2), so registrations made now become redundant rather
|
|
146
|
+
* than wrong.
|
|
147
|
+
*/
|
|
148
|
+
export declare function setPriceUpdateDataSource(source: PriceUpdateDataSource): void;
|
|
149
|
+
/**
|
|
150
|
+
* Test-only. The registration is process-wide by design, so without this one
|
|
151
|
+
* test's source would leak into the next.
|
|
152
|
+
*/
|
|
153
|
+
export declare function clearPriceUpdateDataSource(): void;
|
|
154
|
+
/**
|
|
155
|
+
* The source a newly-constructed `SuilendClient` should start with: ALWAYS the
|
|
156
|
+
* late-resolving wrapper, never the registered source directly.
|
|
157
|
+
*
|
|
158
|
+
* Returning the registered source when one happened to exist made resolution
|
|
159
|
+
* depend on construction order after all — a client built before registration
|
|
160
|
+
* followed the registry, one built after snapshotted it. So a re-registration (a
|
|
161
|
+
* provider re-running on hot reload, a refreshed credential behind the source)
|
|
162
|
+
* left every already-built client calling the source it replaced, which is the
|
|
163
|
+
* same silent-divergence failure this seam exists to prevent, reached through
|
|
164
|
+
* timing instead of a missed call site.
|
|
165
|
+
*
|
|
166
|
+
* Per-instance assignment still wins, because the field stays public and
|
|
167
|
+
* reassignable; this only decides what a client starts with.
|
|
168
|
+
*/
|
|
169
|
+
export declare function resolvePriceUpdateDataSource(): PriceUpdateDataSource;
|
package/lib/pyth.js
CHANGED
|
@@ -180,3 +180,86 @@ export const resolvePythConnection = async (pythConnectionOverride, fallbackPyth
|
|
|
180
180
|
const pythEndpoint = await getWorkingPythEndpoint(fallbackPythEndpoint);
|
|
181
181
|
return createHermesPriceFeedSource(new HermesClient(pythEndpoint, hermesConnectionConfig(hermesConfig)));
|
|
182
182
|
};
|
|
183
|
+
/**
|
|
184
|
+
* The SDK's default: it resolves the registered source LATE, and fails only if
|
|
185
|
+
* there still isn't one.
|
|
186
|
+
*
|
|
187
|
+
* Late resolution is the point. A client reads this default at construction, so
|
|
188
|
+
* a default that captured "nothing registered" would leave every client built
|
|
189
|
+
* before startup finished permanently broken — and consumers construct clients
|
|
190
|
+
* inside React hooks and module initialisers, where ordering against an app's
|
|
191
|
+
* own bootstrap is not something the SDK can dictate. Deferring to call time
|
|
192
|
+
* means registration order simply does not matter.
|
|
193
|
+
*
|
|
194
|
+
* When there genuinely is no source, it names the problem rather than returning
|
|
195
|
+
* something unusable. There is no default that could work: `WORMHOLE_STATE_ID`
|
|
196
|
+
* is unconditionally the pro-compatible deployment, whose vendored wormhole
|
|
197
|
+
* holds a single guardian set, so a public-Hermes VAA carries the Wormhole
|
|
198
|
+
* network's set 7 and aborts in `dynamic_field::borrow_child_object` as the
|
|
199
|
+
* first command of the user's transaction. Shipping public Hermes here — which
|
|
200
|
+
* is what this SDK did — was not a lenient default but a guaranteed on-chain
|
|
201
|
+
* abort, deferred until a feed drifted past the staleness gate.
|
|
202
|
+
*/
|
|
203
|
+
const deferredPriceUpdateDataSource = {
|
|
204
|
+
getPriceFeedsUpdateData: (priceIds) => {
|
|
205
|
+
if (registeredPriceUpdateDataSource) {
|
|
206
|
+
return registeredPriceUpdateDataSource.getPriceFeedsUpdateData(priceIds);
|
|
207
|
+
}
|
|
208
|
+
return Promise.reject(new Error("@suilend/sdk: no price-update source is registered, so an on-chain " +
|
|
209
|
+
"price update cannot be built. Call setPriceUpdateDataSource() at " +
|
|
210
|
+
"startup with a source backed by the pro-compatible Pyth deployment " +
|
|
211
|
+
"(public Hermes cannot be used: its VAAs are signed by a guardian set " +
|
|
212
|
+
"the linked wormhole instance does not hold, and verification aborts)."));
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
let registeredPriceUpdateDataSource;
|
|
216
|
+
/**
|
|
217
|
+
* Register the process-wide source for on-chain price updates. Call at startup;
|
|
218
|
+
* clients constructed BEFORE the call still pick it up, because the SDK default
|
|
219
|
+
* resolves late (see `deferredPriceUpdateDataSource`).
|
|
220
|
+
*
|
|
221
|
+
* Process-wide rather than a constructor argument on purpose: consumers build a
|
|
222
|
+
* `SuilendClient` in many places (perpetual-ui alone has 17 `initialize` call
|
|
223
|
+
* sites across four apps), and a per-site argument means the site somebody adds
|
|
224
|
+
* next silently reverts to the broken path. One registration covers every
|
|
225
|
+
* instance, including ones constructed by code the caller does not own.
|
|
226
|
+
*
|
|
227
|
+
* Resolution order, most specific first:
|
|
228
|
+
* 1. `client.pythConnection = …` — a per-instance assignment always wins, and
|
|
229
|
+
* is how the indexer injects its authenticated failover connection.
|
|
230
|
+
* 2. whatever was registered here.
|
|
231
|
+
* 3. the SDK default.
|
|
232
|
+
*
|
|
233
|
+
* That order is load-bearing for the planned change to have the SDK resolve its
|
|
234
|
+
* own default endpoint: adding a real default at (3) cannot fight a consumer
|
|
235
|
+
* that registered at (2), so registrations made now become redundant rather
|
|
236
|
+
* than wrong.
|
|
237
|
+
*/
|
|
238
|
+
export function setPriceUpdateDataSource(source) {
|
|
239
|
+
registeredPriceUpdateDataSource = source;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Test-only. The registration is process-wide by design, so without this one
|
|
243
|
+
* test's source would leak into the next.
|
|
244
|
+
*/
|
|
245
|
+
export function clearPriceUpdateDataSource() {
|
|
246
|
+
registeredPriceUpdateDataSource = undefined;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* The source a newly-constructed `SuilendClient` should start with: ALWAYS the
|
|
250
|
+
* late-resolving wrapper, never the registered source directly.
|
|
251
|
+
*
|
|
252
|
+
* Returning the registered source when one happened to exist made resolution
|
|
253
|
+
* depend on construction order after all — a client built before registration
|
|
254
|
+
* followed the registry, one built after snapshotted it. So a re-registration (a
|
|
255
|
+
* provider re-running on hot reload, a refreshed credential behind the source)
|
|
256
|
+
* left every already-built client calling the source it replaced, which is the
|
|
257
|
+
* same silent-divergence failure this seam exists to prevent, reached through
|
|
258
|
+
* timing instead of a missed call site.
|
|
259
|
+
*
|
|
260
|
+
* Per-instance assignment still wins, because the field stays public and
|
|
261
|
+
* reassignable; this only decides what a client starts with.
|
|
262
|
+
*/
|
|
263
|
+
export function resolvePriceUpdateDataSource() {
|
|
264
|
+
return deferredPriceUpdateDataSource;
|
|
265
|
+
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@suilend/sdk","version":"
|
|
1
|
+
{"name":"@suilend/sdk","version":"10.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/_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/source/0x1":"./_generated/_dependencies/source/0x1/index.js","./_generated/_dependencies/source/0x2":"./_generated/_dependencies/source/0x2/index.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/index.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","./_generated/_dependencies/source/0x1/ascii/structs":"./_generated/_dependencies/source/0x1/ascii/structs.js","./_generated/_dependencies/source/0x1/option/structs":"./_generated/_dependencies/source/0x1/option/structs.js","./_generated/_dependencies/source/0x1/type-name/structs":"./_generated/_dependencies/source/0x1/type-name/structs.js","./_generated/_dependencies/source/0x2/bag/structs":"./_generated/_dependencies/source/0x2/bag/structs.js","./_generated/_dependencies/source/0x2/balance/structs":"./_generated/_dependencies/source/0x2/balance/structs.js","./_generated/_dependencies/source/0x2/object/structs":"./_generated/_dependencies/source/0x2/object/structs.js","./_generated/_dependencies/source/0x2/object-table/structs":"./_generated/_dependencies/source/0x2/object-table/structs.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs.js"},"types":"./index.d.ts","scripts":{"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.5.0","@cetusprotocol/aggregator-sdk":"^1.5.7","@flowx-finance/sdk":"^2.1.0","@pythnetwork/hermes-client":"3.1.0","@pythnetwork/pyth-sui-js":"4.0.0","@suilend/springsui-sdk":"^4.0.0","bignumber.js":"^11.1.5","bn.js":"^5.2.2","crypto-js":"^4.2.0","lodash":"^4.17.21","p-limit":"7.3.1","uuid":"^14.0.1"},"devDependencies":{"@mysten/bcs":"^2.0.5","@mysten/sui":"2.23.2","@suilend/sui-core":"^1.0.0","@tsconfig/recommended":"^1.0.8","@types/bn.js":"^5.2.0","@types/lodash":"^4.17.25","@types/node":"^26.1.2","fast-check":"^4.9.0","prettier":"^3.3.3","ts-node":"^10.9.2","typescript":"^6.0.3","vitest":"4.1.10"},"peerDependencies":{"@mysten/bcs":"^2.0.5","@mysten/sui":">=2.22.1 <3","@suilend/sui-core":"^1.0.0"},"type":"module"}
|