@suilend/sdk 14.2.1 → 14.3.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/README.md +39 -0
- package/api/events.js +3 -2
- package/client.js +83 -91
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/lib/cetusArguments.d.ts +6 -0
- package/lib/cetusArguments.js +2 -0
- package/lib/initialize.js +19 -13
- package/lib/strategyOwnerCap.d.ts +1 -1
- package/lib/strategyOwnerCap.js +40 -52
- package/network.d.ts +27 -0
- package/network.js +59 -0
- package/package.json +1 -1
- package/strategies.d.ts +1 -1
- package/strategies.js +26 -28
- package/swap/transaction.js +5 -4
- package/utils/obligation.js +5 -4
- package/_generated/suilend/index.d.ts +0 -6
- package/_generated/suilend/index.js +0 -12
package/README.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
A TypeScript SDK for interacting with the Suilend program published on npm as [`@suilend/sdk`](https://www.npmjs.com/package/@suilend/sdk).
|
|
4
4
|
|
|
5
|
+
### Other networks
|
|
6
|
+
|
|
7
|
+
The SDK targets mainnet by default. A process that runs against localnet calls
|
|
8
|
+
`setSuilendNetwork` once at startup, before it builds any client:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { SUILEND_MAINNET_NETWORK, setSuilendNetwork } from "@suilend/sdk";
|
|
12
|
+
import { freshPublishEnv } from "@suilend/sui-core";
|
|
13
|
+
|
|
14
|
+
setSuilendNetwork({
|
|
15
|
+
name: "localnet",
|
|
16
|
+
env: freshPublishEnv(SUILEND_MAINNET_NETWORK.env, { suilend: suilendPackageId }),
|
|
17
|
+
mainLendingMarket: { id: lendingMarketId, type: lendingMarketType },
|
|
18
|
+
suilendUpgradeCapId,
|
|
19
|
+
latestMarketVersion: BigInt(8),
|
|
20
|
+
publishedAtByMarketVersion: new Map(),
|
|
21
|
+
pythStateId,
|
|
22
|
+
wormholeStateId,
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Give `freshPublishEnv` every dependency the localnet publish replaced as well,
|
|
27
|
+
such as `liquid-staking` and `sprungsui`. Call `setSpringSuiNetwork` from
|
|
28
|
+
`@suilend/springsui-sdk` at startup too: `setSuilendNetwork` does not set it,
|
|
29
|
+
and strategy and LST reads such as `fetchStrategyLstMap` take the SpringSui
|
|
30
|
+
UpgradeCap from it. `SuilendClient.initialize` then reads
|
|
31
|
+
that network's MAIN market and UpgradeCap, and generated move calls and type
|
|
32
|
+
names follow its package env.
|
|
33
|
+
Exported constants such as `LENDING_MARKET_ID` stay the mainnet values; read
|
|
34
|
+
`getSuilendNetwork()` for the active ones. The SDK's Suilend API reads, such as
|
|
35
|
+
the strategy TVL and LST info, build their URL from `getApiUrl()` in
|
|
36
|
+
`@suilend/sui-core`, so `setApiUrl` moves them with sui-core's own helpers. Strategies on MAIN use the active
|
|
37
|
+
network's MAIN market. Without `strategyWrapper`, strategy calls throw, and
|
|
38
|
+
owned-obligation reads skip strategy owner caps. Setting a network with the same
|
|
39
|
+
name, UpgradeCaps and suilend original id and published-at again keeps the package
|
|
40
|
+
`SuilendClient.initialize` resolved; any other network drops it, so initialize
|
|
41
|
+
again after switching. The name `mainnet` belongs to the generated mainnet env. A mainnet fork keeps
|
|
42
|
+
`SUILEND_MAINNET_NETWORK`.
|
|
43
|
+
|
|
5
44
|
### Pyth access
|
|
6
45
|
|
|
7
46
|
Public Hermes requires a Pyth API key, so `initializeSuilend` and `initializeSuilendAll` need yours. Without it, every price read fails with 401. The Suilend API's Pyth routes, `/proxy/latest-prices` and `/proxy/price-update-data`, spend our key and only answer Suilend's own frontends, so a third-party browser page cannot use them.
|
package/api/events.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assertResponseOk, getApiUrl } from "@suilend/sui-core";
|
|
2
2
|
/**
|
|
3
3
|
* Note: This SDK function is experimental and may change or require authentication in the future.
|
|
4
4
|
*/
|
|
5
5
|
export const fetchDownsampledApiReserveAssetDataEvents = async (reserveId, days, sampleIntervalS) => {
|
|
6
|
-
const url = `${
|
|
6
|
+
const url = `${getApiUrl()}/events/downsampled-reserve-asset-data?reserveId=${reserveId}&days=${days}&sampleIntervalS=${sampleIntervalS}`;
|
|
7
7
|
const res = await fetch(url);
|
|
8
|
+
assertResponseOk(res, "Downsampled reserve asset data events request");
|
|
8
9
|
const json = await res.json();
|
|
9
10
|
return json;
|
|
10
11
|
};
|
package/client.js
CHANGED
|
@@ -6,9 +6,7 @@ import { extractCTokenCoinType, getAllCoins, getSpendableCoin, } from "@suilend/
|
|
|
6
6
|
import { phantom } from "./_generated/_framework/reified.js";
|
|
7
7
|
import { Decimal } from "./_generated/suilend/decimal/structs.js";
|
|
8
8
|
import { confidenceShare, decimalToBigNumber, } from "./utils/simulate.js";
|
|
9
|
-
import {
|
|
10
|
-
import { getPublishedAt } from "./_generated/_envs/index.js";
|
|
11
|
-
import { PACKAGE_ID } from "./_generated/suilend/index.js";
|
|
9
|
+
import { getOriginalId, getPublishedAt, getTypeOrigin, } from "./_generated/_envs/index.js";
|
|
12
10
|
import { addPoolReward, borrowRequest, cancelPoolReward, claimFees, claimRewards, claimRewardsAndDeposit, closePoolReward, depositCtokensIntoObligation, depositLiquidityAndMintCtokens, fulfillLiquidityRequest, liquidate, migrate, newObligationOwnerCap, rebalanceStaker, redeemCtokensAndWithdrawLiquidityRequest, repay, reserveConfigBuilder, setFeeReceivers, unstakeSuiFromStaker, updateRateLimiterConfig, updateReserveConfig, withdrawCtokens, } from "./_generated/suilend/lending-market/functions.js";
|
|
13
11
|
import { LendingMarket, ObligationOwnerCap, } from "./_generated/suilend/lending-market/structs.js";
|
|
14
12
|
import { createLendingMarket } from "./_generated/suilend/lending-market-registry/functions.js";
|
|
@@ -18,21 +16,11 @@ import { build as buildReserveConfig, createReserveConfig, setBorrowFeeBps, setB
|
|
|
18
16
|
import { addReserveProCompatible, addReserveV2ProCompatible, changeReservePriceFeedProCompatible, priceInfoPublishTime, refreshReservePriceProCompatible, } from "./lib/proCompatible.js";
|
|
19
17
|
import { resolvePriceUpdateDataSource, } from "./lib/pyth.js";
|
|
20
18
|
import { Side } from "./lib/types.js";
|
|
19
|
+
import { SUILEND_MAINNET_NETWORK, getStrategyWrapperNetwork, getSuilendNetwork, isSameSuilendNetwork, setPublishedAt, } from "./network.js";
|
|
21
20
|
import { chunkedMultiGet } from "./utils/obligation.js";
|
|
22
21
|
const SUI_COINTYPE = "0x2::sui::SUI";
|
|
23
22
|
const NORMALIZED_SUI_COINTYPE = normalizeStructTag(SUI_COINTYPE);
|
|
24
23
|
const isSui = (coinType) => normalizeStructTag(coinType) === NORMALIZED_SUI_COINTYPE;
|
|
25
|
-
// Pyth Core's 2026-08-18 upgrade. These are the UPGRADED state objects, which
|
|
26
|
-
// pair with the pro-compatible Pyth package the Move contracts now link against
|
|
27
|
-
// (see move/contracts/suilend/Move.toml). The pre-upgrade values were
|
|
28
|
-
// Wormhole 0xaeab97f9… and Pyth 0x1f931023….
|
|
29
|
-
//
|
|
30
|
-
// MUST ship in the same release as the suilend package upgrade. Pointing the
|
|
31
|
-
// SDK at the upgraded state while the published package still links the legacy
|
|
32
|
-
// Pyth package breaks every on-chain price update -- the object passed to
|
|
33
|
-
// refresh would come from a package the contract does not accept.
|
|
34
|
-
const WORMHOLE_STATE_ID = "0xdbca52b9fb4f712e25f61f974586d93ac541bcf8389564f0323bb07215168b5c";
|
|
35
|
-
const PYTH_STATE_ID = "0x03719fae774ddab3cfcaa53bbc046f0cbe21410019b6280811bf3f9f4b05839d";
|
|
36
24
|
const normalizePriceIdentifier = (id) => id.toLowerCase().replace(/^0x/, "");
|
|
37
25
|
// Mirrors suilend::oracles's MAX_FORWARD_SECONDS (move/contracts/suilend/sources/oracles.move);
|
|
38
26
|
// `refresh_reserve_price` now rejects a forward-dated price the same as a stale one.
|
|
@@ -48,36 +36,28 @@ export function needsPriceRefresh(stalenessSeconds) {
|
|
|
48
36
|
return stalenessSeconds > 20 || stalenessSeconds < -MAX_FORWARD_SECONDS;
|
|
49
37
|
}
|
|
50
38
|
export const ADMIN_ADDRESS = "0xb1ffbc2e1915f44b8f271a703becc1bf8aa79bc22431a58900a102892b783c25";
|
|
51
|
-
|
|
52
|
-
// A suilend package accepts only markets whose `version` equals the
|
|
53
|
-
// CURRENT_VERSION it was compiled with, and the UpgradeCap names the newest
|
|
54
|
-
// package before any market migrates to it. So only the newest market version
|
|
55
|
-
// follows the cap; each older version pins the last package built for it.
|
|
56
|
-
const LATEST_MARKET_VERSION = BigInt(8);
|
|
57
|
-
const PUBLISHED_AT_BY_MARKET_VERSION = new Map([
|
|
58
|
-
[
|
|
59
|
-
BigInt(7),
|
|
60
|
-
"0x59672975e15c58ffc9450f5236b6aa9fa2407d94b8081e634778aa01957d8c6f",
|
|
61
|
-
],
|
|
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;
|
|
39
|
+
let strategyWrapperPackage;
|
|
69
40
|
export function getStrategyWrapperPackageId() {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
41
|
+
const network = getSuilendNetwork();
|
|
42
|
+
const strategyWrapper = getStrategyWrapperNetwork();
|
|
43
|
+
const resolved = strategyWrapperPackage &&
|
|
44
|
+
isSameSuilendNetwork(strategyWrapperPackage.network, network)
|
|
45
|
+
? strategyWrapperPackage.resolved
|
|
46
|
+
: strategyWrapper.defaultPackageId;
|
|
47
|
+
if (typeof resolved !== "string")
|
|
48
|
+
throw new Error(`The strategy_wrapper package is unresolved: reading its UpgradeCap ${strategyWrapper.upgradeCapId} failed at MAIN lending market version ${network.latestMarketVersion}. Retry SuilendClient.initialize before building strategy transactions.`, { cause: resolved.readError });
|
|
49
|
+
return resolved;
|
|
73
50
|
}
|
|
74
51
|
export function setStrategyWrapperPackageId(packageId) {
|
|
75
|
-
strategyWrapperPackage =
|
|
52
|
+
strategyWrapperPackage = {
|
|
53
|
+
network: getSuilendNetwork(),
|
|
54
|
+
resolved: packageId,
|
|
55
|
+
};
|
|
76
56
|
}
|
|
77
57
|
export const LENDING_MARKET_REGISTRY_ID = "0x64faff8d91a56c4f55debbb44767b009ee744a70bc2cc8e3bbd2718c92f85931";
|
|
78
58
|
export const [LENDING_MARKET_ID, LENDING_MARKET_TYPE] = [
|
|
79
|
-
|
|
80
|
-
|
|
59
|
+
SUILEND_MAINNET_NETWORK.mainLendingMarket.id,
|
|
60
|
+
SUILEND_MAINNET_NETWORK.mainLendingMarket.type,
|
|
81
61
|
];
|
|
82
62
|
export const [STEAMM_LM_LENDING_MARKET_ID, STEAMM_LM_LENDING_MARKET_TYPE] = [
|
|
83
63
|
"0xc1888ec1b81a414e427a44829310508352aec38252ee0daa9f8b181b6947de9f",
|
|
@@ -258,44 +238,57 @@ function applyPublishedAt(publishedAt, logPackageId) {
|
|
|
258
238
|
console.log("@suilend/sdk | publishedAt:", publishedAt);
|
|
259
239
|
setPublishedAt(publishedAt);
|
|
260
240
|
}
|
|
261
|
-
function startLatestPackageIdRead(suiGrpcClient) {
|
|
262
|
-
const latestPackageId = getLatestPackageId(suiGrpcClient,
|
|
241
|
+
function startLatestPackageIdRead(suiGrpcClient, network) {
|
|
242
|
+
const latestPackageId = getLatestPackageId(suiGrpcClient, network.suilendUpgradeCapId);
|
|
263
243
|
// Read eagerly to overlap the market fetch, but unused while MAIN's version
|
|
264
244
|
// is pinned: an unobserved rejection would crash a bun process.
|
|
265
245
|
latestPackageId.catch(() => { });
|
|
266
246
|
return latestPackageId;
|
|
267
247
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
248
|
+
function assertNetworkUnchanged(network) {
|
|
249
|
+
const active = getSuilendNetwork();
|
|
250
|
+
if (!isSameSuilendNetwork(active, network))
|
|
251
|
+
throw new Error(`The Suilend network changed from ${network.name} to ${active.name} while SuilendClient.initialize ran. Call initialize again.`);
|
|
252
|
+
}
|
|
253
|
+
async function applyPackagesForMainVersion(suiGrpcClient, network, mainVersion, latestPackageId, logPackageId) {
|
|
254
|
+
const { strategyWrapper } = network;
|
|
255
|
+
if (mainVersion === network.latestMarketVersion) {
|
|
256
|
+
const [publishedAt, strategyWrapperResolved] = await Promise.all([
|
|
271
257
|
latestPackageId,
|
|
272
|
-
|
|
258
|
+
strategyWrapper &&
|
|
259
|
+
getLatestPackageId(suiGrpcClient, strategyWrapper.upgradeCapId).catch((readError) => ({ readError })),
|
|
273
260
|
]);
|
|
261
|
+
assertNetworkUnchanged(network);
|
|
274
262
|
applyPublishedAt(publishedAt, logPackageId);
|
|
275
|
-
|
|
263
|
+
if (strategyWrapperResolved)
|
|
264
|
+
strategyWrapperPackage = { network, resolved: strategyWrapperResolved };
|
|
276
265
|
return;
|
|
277
266
|
}
|
|
278
|
-
const publishedAt =
|
|
279
|
-
const
|
|
280
|
-
|
|
267
|
+
const publishedAt = network.publishedAtByMarketVersion.get(mainVersion);
|
|
268
|
+
const strategyWrapperPackageId = strategyWrapper?.packageIdByMarketVersion.get(mainVersion);
|
|
269
|
+
const missingStrategyWrapper = !!strategyWrapper && !strategyWrapperPackageId;
|
|
270
|
+
if (!publishedAt || missingStrategyWrapper) {
|
|
281
271
|
const unknown = [
|
|
282
272
|
...(publishedAt ? [] : ["suilend"]),
|
|
283
|
-
...(
|
|
273
|
+
...(missingStrategyWrapper ? ["strategy_wrapper"] : []),
|
|
284
274
|
];
|
|
285
|
-
throw new Error(`No ${unknown.join(" or ")} package is known for lending market version ${mainVersion} (MAIN ${
|
|
275
|
+
throw new Error(`No ${unknown.join(" or ")} package is known for lending market version ${mainVersion} (MAIN ${network.mainLendingMarket.id})`);
|
|
286
276
|
}
|
|
277
|
+
assertNetworkUnchanged(network);
|
|
287
278
|
applyPublishedAt(publishedAt, logPackageId);
|
|
288
|
-
|
|
279
|
+
if (strategyWrapperPackageId)
|
|
280
|
+
strategyWrapperPackage = { network, resolved: strategyWrapperPackageId };
|
|
289
281
|
}
|
|
290
|
-
async function readMainVersion(suiGrpcClient) {
|
|
282
|
+
async function readMainVersion(suiGrpcClient, network) {
|
|
283
|
+
const { mainLendingMarket } = network;
|
|
291
284
|
const { object } = await suiGrpcClient.getObject({
|
|
292
|
-
objectId:
|
|
285
|
+
objectId: mainLendingMarket.id,
|
|
293
286
|
include: { content: true },
|
|
294
287
|
});
|
|
295
|
-
const expectedType = `${
|
|
288
|
+
const expectedType = `${getOriginalId("suilend")}::lending_market::LendingMarket<${mainLendingMarket.type}>`;
|
|
296
289
|
if (!object.type ||
|
|
297
290
|
normalizeStructTag(object.type) !== normalizeStructTag(expectedType))
|
|
298
|
-
throw new Error(`object at id ${
|
|
291
|
+
throw new Error(`object at id ${mainLendingMarket.id} is not a ${expectedType} (got ${object.type})`);
|
|
299
292
|
// LendingMarket's BCS starts with its 32-byte UID, then `version: u64`, so
|
|
300
293
|
// the version is read without decoding every reserve.
|
|
301
294
|
return BigInt(bcs.u64().parse(object.content.subarray(32, 40)));
|
|
@@ -304,20 +297,23 @@ async function readMainVersion(suiGrpcClient) {
|
|
|
304
297
|
// once share one MAIN read, and nothing outlives settlement, so a long-running
|
|
305
298
|
// process sees a migrate on its next initialize.
|
|
306
299
|
const mainVersionInFlight = new WeakMap();
|
|
307
|
-
function fetchMainVersion(suiGrpcClient) {
|
|
300
|
+
function fetchMainVersion(suiGrpcClient, network) {
|
|
308
301
|
const inFlight = mainVersionInFlight.get(suiGrpcClient);
|
|
309
|
-
if (inFlight)
|
|
310
|
-
return inFlight;
|
|
311
|
-
const promise = readMainVersion(suiGrpcClient).finally(() =>
|
|
312
|
-
|
|
302
|
+
if (inFlight?.network === network)
|
|
303
|
+
return inFlight.promise;
|
|
304
|
+
const promise = readMainVersion(suiGrpcClient, network).finally(() => {
|
|
305
|
+
if (mainVersionInFlight.get(suiGrpcClient)?.promise === promise)
|
|
306
|
+
mainVersionInFlight.delete(suiGrpcClient);
|
|
307
|
+
});
|
|
308
|
+
mainVersionInFlight.set(suiGrpcClient, { network, promise });
|
|
313
309
|
return promise;
|
|
314
310
|
}
|
|
315
|
-
function isMainMarket(lendingMarketId) {
|
|
311
|
+
function isMainMarket(lendingMarketId, network) {
|
|
316
312
|
return (normalizeSuiObjectId(lendingMarketId) ===
|
|
317
|
-
normalizeSuiObjectId(
|
|
313
|
+
normalizeSuiObjectId(network.mainLendingMarket.id));
|
|
318
314
|
}
|
|
319
|
-
function versionMismatch(lendingMarketId, version, mainVersion) {
|
|
320
|
-
return `lending market ${lendingMarketId} is at version ${version}, but MAIN ${
|
|
315
|
+
function versionMismatch(lendingMarketId, version, mainVersion, network) {
|
|
316
|
+
return `lending market ${lendingMarketId} is at version ${version}, but MAIN ${network.mainLendingMarket.id} is at version ${mainVersion}, so the suilend package chosen for MAIN aborts on its writes`;
|
|
321
317
|
}
|
|
322
318
|
function clientsFromObjects(lendingMarkets, objects, suiGrpcClient) {
|
|
323
319
|
// Paired by objectId rather than by position: BatchGetObjectsResponse
|
|
@@ -343,7 +339,7 @@ function clientsFromObjects(lendingMarkets, objects, suiGrpcClient) {
|
|
|
343
339
|
// Compares the full parameterized type, not just the struct name: an
|
|
344
340
|
// id/type pair built from two drifted lists would otherwise pass and
|
|
345
341
|
// decode under the wrong phantom type.
|
|
346
|
-
const expectedType = normalizeStructTag(`${
|
|
342
|
+
const expectedType = normalizeStructTag(`${getOriginalId("suilend")}::lending_market::LendingMarket<${type}>`);
|
|
347
343
|
if (normalizeStructTag(object.type) !== expectedType)
|
|
348
344
|
throw new Error(`object at id ${id} is not a LendingMarket<${type}> (got ${object.type})`);
|
|
349
345
|
const lendingMarket = LendingMarket.fromBcs(phantom(type), object.content);
|
|
@@ -383,27 +379,22 @@ export class SuilendClient {
|
|
|
383
379
|
// 'getDynamicField')". That is the on-chain price-update path, i.e. every
|
|
384
380
|
// deposit/withdraw/borrow/repay, and nothing read-only touches it, so a
|
|
385
381
|
// typecheck and every page-load check stay green while writes are broken.
|
|
386
|
-
this.pythClient = new SuiPythClient(suiGrpcClient,
|
|
387
|
-
// Deliberately NOT a public-Hermes connection, which is what stood here.
|
|
388
|
-
// `WORMHOLE_STATE_ID` above is unconditionally the pro-compatible
|
|
389
|
-
// deployment, and public Hermes signs with a guardian set that deployment
|
|
390
|
-
// does not hold — so that default could not produce a usable update for any
|
|
391
|
-
// feed, and only looked harmless because `refreshAll` skips the update
|
|
392
|
-
// entirely while a feed is fresh. See `resolvePriceUpdateDataSource`.
|
|
382
|
+
this.pythClient = new SuiPythClient(suiGrpcClient, getSuilendNetwork().pythStateId, getSuilendNetwork().wormholeStateId);
|
|
393
383
|
this.pythConnection = resolvePriceUpdateDataSource();
|
|
394
384
|
}
|
|
395
385
|
static async initialize(lendingMarketId, lendingMarketType, suiGrpcClient, logPackageId) {
|
|
396
|
-
const
|
|
386
|
+
const network = getSuilendNetwork();
|
|
387
|
+
const latestPackageId = startLatestPackageIdRead(suiGrpcClient, network);
|
|
397
388
|
const [lendingMarket, fetchedMainVersion] = await Promise.all([
|
|
398
389
|
LendingMarket.fetch(suiGrpcClient, phantom(lendingMarketType), lendingMarketId),
|
|
399
|
-
isMainMarket(lendingMarketId)
|
|
390
|
+
isMainMarket(lendingMarketId, network)
|
|
400
391
|
? undefined
|
|
401
|
-
: fetchMainVersion(suiGrpcClient),
|
|
392
|
+
: fetchMainVersion(suiGrpcClient, network),
|
|
402
393
|
]);
|
|
403
394
|
const mainVersion = fetchedMainVersion ?? lendingMarket.version;
|
|
404
395
|
if (lendingMarket.version !== mainVersion)
|
|
405
|
-
throw new Error(versionMismatch(lendingMarketId, lendingMarket.version, mainVersion));
|
|
406
|
-
await applyPackagesForMainVersion(suiGrpcClient, mainVersion, latestPackageId, logPackageId);
|
|
396
|
+
throw new Error(versionMismatch(lendingMarketId, lendingMarket.version, mainVersion, network));
|
|
397
|
+
await applyPackagesForMainVersion(suiGrpcClient, network, mainVersion, latestPackageId, logPackageId);
|
|
407
398
|
return new SuilendClient(lendingMarket, suiGrpcClient);
|
|
408
399
|
}
|
|
409
400
|
/**
|
|
@@ -414,8 +405,9 @@ export class SuilendClient {
|
|
|
414
405
|
// Chosen even for an empty list: move-call targets are built off the
|
|
415
406
|
// published-at override regardless of how many clients came back. Like
|
|
416
407
|
// initialize(), a call that fails at any read leaves it unchanged.
|
|
417
|
-
const
|
|
418
|
-
const
|
|
408
|
+
const network = getSuilendNetwork();
|
|
409
|
+
const latestPackageId = startLatestPackageIdRead(suiGrpcClient, network);
|
|
410
|
+
const mainRequested = lendingMarkets.some(({ id }) => isMainMarket(id, network));
|
|
419
411
|
const [objects, fetchedMainVersion] = await Promise.all([
|
|
420
412
|
lendingMarkets.length === 0
|
|
421
413
|
? []
|
|
@@ -425,16 +417,16 @@ export class SuilendClient {
|
|
|
425
417
|
include: { content: true },
|
|
426
418
|
})
|
|
427
419
|
.then((response) => response.objects),
|
|
428
|
-
mainRequested ? undefined : fetchMainVersion(suiGrpcClient),
|
|
420
|
+
mainRequested ? undefined : fetchMainVersion(suiGrpcClient, network),
|
|
429
421
|
]);
|
|
430
422
|
const clients = clientsFromObjects(lendingMarkets, objects, suiGrpcClient);
|
|
431
423
|
const mainVersion = fetchedMainVersion ??
|
|
432
|
-
clients[lendingMarkets.findIndex(({ id }) => isMainMarket(id))]
|
|
424
|
+
clients[lendingMarkets.findIndex(({ id }) => isMainMarket(id, network))]
|
|
433
425
|
.lendingMarket.version;
|
|
434
|
-
await applyPackagesForMainVersion(suiGrpcClient, mainVersion, latestPackageId, logPackageId);
|
|
426
|
+
await applyPackagesForMainVersion(suiGrpcClient, network, mainVersion, latestPackageId, logPackageId);
|
|
435
427
|
for (const { lendingMarket } of clients)
|
|
436
428
|
if (lendingMarket.version !== mainVersion)
|
|
437
|
-
console.warn(`@suilend/sdk | ${versionMismatch(lendingMarket.id, lendingMarket.version, mainVersion)}`);
|
|
429
|
+
console.warn(`@suilend/sdk | ${versionMismatch(lendingMarket.id, lendingMarket.version, mainVersion, network)}`);
|
|
438
430
|
return clients;
|
|
439
431
|
}
|
|
440
432
|
/**
|
|
@@ -451,7 +443,7 @@ export class SuilendClient {
|
|
|
451
443
|
return clients;
|
|
452
444
|
}
|
|
453
445
|
static async getFeeReceivers(suiGrpcClient, lendingMarketId) {
|
|
454
|
-
const json = await fetchDynamicFieldJson(suiGrpcClient, lendingMarketId, `${
|
|
446
|
+
const json = await fetchDynamicFieldJson(suiGrpcClient, lendingMarketId, `${getTypeOrigin("suilend", "lending_market::FeeReceiversKey")}::lending_market::FeeReceiversKey`);
|
|
455
447
|
const receivers = json?.value?.receivers;
|
|
456
448
|
const weights = json?.value?.weights;
|
|
457
449
|
return { receivers, weights };
|
|
@@ -503,8 +495,8 @@ export class SuilendClient {
|
|
|
503
495
|
return ownerCap;
|
|
504
496
|
}
|
|
505
497
|
static async getObligationOwnerCaps(ownerId, lendingMarketTypeArgs, suiGrpcClient) {
|
|
506
|
-
const allObjs = await listAllOwnedObjects(suiGrpcClient, ownerId, `${
|
|
507
|
-
const type = normalizeStructTag(`${
|
|
498
|
+
const allObjs = await listAllOwnedObjects(suiGrpcClient, ownerId, `${getOriginalId("suilend")}::lending_market::ObligationOwnerCap`, { content: true });
|
|
499
|
+
const type = normalizeStructTag(`${getOriginalId("suilend")}::lending_market::ObligationOwnerCap<${lendingMarketTypeArgs[0]}>`);
|
|
508
500
|
return allObjs
|
|
509
501
|
.filter((obj) => normalizeStructTag(obj.type) === type)
|
|
510
502
|
.map((obj) => ObligationOwnerCap.fromBcs(phantom(lendingMarketTypeArgs[0]), obj.content));
|
|
@@ -533,8 +525,8 @@ export class SuilendClient {
|
|
|
533
525
|
return SuilendClient.getObligation(obligationId, this.lendingMarket.$typeArgs, this.suiGrpcClient);
|
|
534
526
|
}
|
|
535
527
|
static async getLendingMarketOwnerCapId(ownerId, lendingMarketTypeArgs, suiGrpcClient) {
|
|
536
|
-
const allObjs = await listAllOwnedObjects(suiGrpcClient, ownerId, `${
|
|
537
|
-
const type = normalizeStructTag(`${
|
|
528
|
+
const allObjs = await listAllOwnedObjects(suiGrpcClient, ownerId, `${getOriginalId("suilend")}::lending_market::LendingMarketOwnerCap`);
|
|
529
|
+
const type = normalizeStructTag(`${getOriginalId("suilend")}::lending_market::LendingMarketOwnerCap<${lendingMarketTypeArgs[0]}>`);
|
|
538
530
|
return allObjs.find((obj) => normalizeStructTag(obj.type) === type)
|
|
539
531
|
?.objectId;
|
|
540
532
|
}
|
|
@@ -867,7 +859,7 @@ export class SuilendClient {
|
|
|
867
859
|
const [exemption] = transaction.moveCall({
|
|
868
860
|
target: `0x1::option::none`,
|
|
869
861
|
typeArguments: [
|
|
870
|
-
`${
|
|
862
|
+
`${getTypeOrigin("suilend", "lending_market::RateLimiterExemption")}::lending_market::RateLimiterExemption<${this.lendingMarket.$typeArgs[0]}, ${coinType}>`,
|
|
871
863
|
],
|
|
872
864
|
arguments: [],
|
|
873
865
|
});
|
|
@@ -951,7 +943,7 @@ export class SuilendClient {
|
|
|
951
943
|
const [optionalExemption] = transaction.moveCall({
|
|
952
944
|
target: `0x1::option::some`,
|
|
953
945
|
typeArguments: [
|
|
954
|
-
`${
|
|
946
|
+
`${getTypeOrigin("suilend", "lending_market::RateLimiterExemption")}::lending_market::RateLimiterExemption<${this.lendingMarket.$typeArgs[0]}, ${withdrawCoinType}>`,
|
|
955
947
|
],
|
|
956
948
|
arguments: [exemption],
|
|
957
949
|
});
|
|
@@ -1000,7 +992,7 @@ export class SuilendClient {
|
|
|
1000
992
|
const [exemption] = transaction.moveCall({
|
|
1001
993
|
target: `0x1::option::none`,
|
|
1002
994
|
typeArguments: [
|
|
1003
|
-
`${
|
|
995
|
+
`${getTypeOrigin("suilend", "lending_market::RateLimiterExemption")}::lending_market::RateLimiterExemption<${this.lendingMarket.$typeArgs[0]}, ${coinType}>`,
|
|
1004
996
|
],
|
|
1005
997
|
arguments: [],
|
|
1006
998
|
});
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AggregatorClient } from "@cetusprotocol/aggregator-sdk";
|
|
2
|
+
import type { Transaction, TransactionArgument } from "@mysten/sui/transactions";
|
|
3
|
+
type CetusSwapParams = Parameters<AggregatorClient["routerSwap"]>[0];
|
|
4
|
+
export declare const cetusTransaction: (transaction: Transaction) => CetusSwapParams["txb"];
|
|
5
|
+
export declare const cetusInputCoin: (coin: TransactionArgument) => CetusSwapParams["inputCoin"];
|
|
6
|
+
export {};
|
package/lib/initialize.js
CHANGED
|
@@ -3,7 +3,7 @@ import BigNumber from "bignumber.js";
|
|
|
3
3
|
import pLimit from "p-limit";
|
|
4
4
|
import { NORMALIZED_ALKIMI_COINTYPE, NORMALIZED_AUSD_COINTYPE, NORMALIZED_BLUE_COINTYPE, NORMALIZED_BUCK_COINTYPE, NORMALIZED_DEEP_COINTYPE, NORMALIZED_DMC_COINTYPE, NORMALIZED_FUD_COINTYPE, NORMALIZED_HAEDAL_COINTYPE, NORMALIZED_HIPPO_COINTYPE, NORMALIZED_IKA_COINTYPE, NORMALIZED_KOBAN_COINTYPE, NORMALIZED_LBTC_COINTYPE, NORMALIZED_NS_COINTYPE, NORMALIZED_SEND_COINTYPE, NORMALIZED_SEND_POINTS_S1_COINTYPE, NORMALIZED_SEND_POINTS_S2_COINTYPE, NORMALIZED_SOL_COINTYPE, NORMALIZED_SUI_COINTYPE, NORMALIZED_UP_COINTYPE, NORMALIZED_USDB_COINTYPE, NORMALIZED_USDC_COINTYPE, NORMALIZED_USDsui_COINTYPE, NORMALIZED_WAL_COINTYPE, NORMALIZED_WBTC_COINTYPE, NORMALIZED_WETH_COINTYPE, NORMALIZED_XAUm_COINTYPE, NORMALIZED_eEARN_COINTYPE, NORMALIZED_eTHIRD_COINTYPE, NORMALIZED_flSUI_COINTYPE, NORMALIZED_fpSUI_COINTYPE, NORMALIZED_fudSUI_COINTYPE, NORMALIZED_iSUI_COINTYPE, NORMALIZED_jugSUI_COINTYPE, NORMALIZED_kSUI_COINTYPE, NORMALIZED_mSUI_COINTYPE, NORMALIZED_mUSD_COINTYPE, NORMALIZED_oshiSUI_COINTYPE, NORMALIZED_sSUI_COINTYPE, NORMALIZED_sdeUSD_COINTYPE, NORMALIZED_stratSUI_COINTYPE, NORMALIZED_suiETH_COINTYPE, NORMALIZED_suiUSDT_COINTYPE, NORMALIZED_suiUSDe_COINTYPE, NORMALIZED_suiWBTC_COINTYPE, NORMALIZED_trevinSUI_COINTYPE, NORMALIZED_upSUI_COINTYPE, NORMALIZED_wUSDC_COINTYPE, NORMALIZED_wUSDT_COINTYPE, NORMALIZED_xBTC_COINTYPE, NORMALIZED_yapSUI_COINTYPE, TEMPORARY_PYTH_PRICE_FEED_COINTYPES, getCoinMetadataMapPartial, getPrices, isSendPoints, isSteammPoints, } from "@suilend/sui-core";
|
|
5
5
|
import { phantom } from "../_generated/_framework/reified.js";
|
|
6
|
-
import {
|
|
6
|
+
import { getOriginalId } from "../_generated/_envs/index.js";
|
|
7
7
|
import { ObligationOwnerCap } from "../_generated/suilend/lending-market/structs.js";
|
|
8
8
|
import { Obligation } from "../_generated/suilend/obligation/structs.js";
|
|
9
9
|
import { LENDING_MARKET_ID, SuilendClient, listAllOwnedObjects, } from "../client.js";
|
|
@@ -12,7 +12,8 @@ import { chunkedMultiGetSettled } from "../utils/obligation.js";
|
|
|
12
12
|
import * as simulate from "../utils/simulate.js";
|
|
13
13
|
import { WAD } from "./constants.js";
|
|
14
14
|
import { resolvePythConnection } from "./pyth.js";
|
|
15
|
-
import {
|
|
15
|
+
import { getStrategyWrapperNetwork, getSuilendNetwork } from "../network.js";
|
|
16
|
+
import { STRATEGY_TYPE_INFO_MAP } from "./strategyOwnerCap.js";
|
|
16
17
|
const BITWISE_LENDING_MARKET_ID = "0x2d7a85c0ad7c4d3c9c89a3785e32aa8d83ef3034148f49ce2d7c441bbba227be";
|
|
17
18
|
const EMBER_LENDING_MARKET_ID = "0x74d92cb095b618f344486f77bcce87fbffc0fe0b46584bb1828bb291a222dda8";
|
|
18
19
|
const SECURITIZE_LENDING_MARKET_ID = "0x13ec4438ef30dce971edde6e542b82c17a87fc2afeeee4be383b49f66d97a73b";
|
|
@@ -485,8 +486,8 @@ const toStrategyOwnerCap = (json) => {
|
|
|
485
486
|
obligationId: cap.inner_cap.obligation_id,
|
|
486
487
|
};
|
|
487
488
|
};
|
|
488
|
-
const
|
|
489
|
-
const
|
|
489
|
+
const obligationOwnerCapStruct = () => `${getOriginalId("suilend")}::lending_market::ObligationOwnerCap`;
|
|
490
|
+
const strategyOwnerCapStruct = () => `${getStrategyWrapperNetwork().typeOriginId}::strategy_wrapper::StrategyOwnerCap`;
|
|
490
491
|
const capType = (capStructType, lendingMarketType) => normalizeStructTag(`${capStructType}<${lendingMarketType}>`);
|
|
491
492
|
const lendingMarketTypeOf = (type) => {
|
|
492
493
|
const [lendingMarketType] = parseStructTag(type).typeParams;
|
|
@@ -496,15 +497,17 @@ const lendingMarketTypeOf = (type) => {
|
|
|
496
497
|
? lendingMarketType
|
|
497
498
|
: normalizeStructTag(lendingMarketType);
|
|
498
499
|
};
|
|
499
|
-
const
|
|
500
|
+
const hasStrategyWrapper = () => !!getSuilendNetwork().strategyWrapper;
|
|
501
|
+
const hasStrategies = (suilendClient) => hasStrategyWrapper() &&
|
|
502
|
+
Object.values(STRATEGY_TYPE_INFO_MAP).some((info) => info.lendingMarketId === suilendClient.lendingMarket.id);
|
|
500
503
|
const listOwnedCaps = async (suiGrpcClient, address, includeStrategyOwnerCaps) => {
|
|
501
504
|
const [strategyObjects, ownerCapObjects] = await Promise.all([
|
|
502
505
|
includeStrategyOwnerCaps
|
|
503
|
-
? listAllOwnedObjects(suiGrpcClient, address,
|
|
506
|
+
? listAllOwnedObjects(suiGrpcClient, address, strategyOwnerCapStruct(), {
|
|
504
507
|
json: true,
|
|
505
508
|
})
|
|
506
509
|
: [],
|
|
507
|
-
listAllOwnedObjects(suiGrpcClient, address,
|
|
510
|
+
listAllOwnedObjects(suiGrpcClient, address, obligationOwnerCapStruct(), {
|
|
508
511
|
content: true,
|
|
509
512
|
}),
|
|
510
513
|
]);
|
|
@@ -527,12 +530,15 @@ const listOwnedCaps = async (suiGrpcClient, address, includeStrategyOwnerCaps) =
|
|
|
527
530
|
};
|
|
528
531
|
const selectMarketCaps = (owned, suilendClient) => {
|
|
529
532
|
const lendingMarketType = suilendClient.lendingMarket.$typeArgs[0];
|
|
530
|
-
const
|
|
531
|
-
const
|
|
533
|
+
const obligationOwnerCapType = capType(obligationOwnerCapStruct(), lendingMarketType);
|
|
534
|
+
const strategyCapStruct = hasStrategies(suilendClient)
|
|
535
|
+
? strategyOwnerCapStruct()
|
|
536
|
+
: undefined;
|
|
537
|
+
const strategyOwnerCapType = strategyCapStruct && capType(strategyCapStruct, lendingMarketType);
|
|
532
538
|
return {
|
|
533
|
-
strategyOwnerCaps:
|
|
539
|
+
strategyOwnerCaps: strategyCapStruct
|
|
534
540
|
? owned.strategyOwnerCaps
|
|
535
|
-
.filter((soc) => capType(
|
|
541
|
+
.filter((soc) => capType(strategyCapStruct, soc.lendingMarketType) ===
|
|
536
542
|
strategyOwnerCapType)
|
|
537
543
|
.map(({ id, strategyType, obligationOwnerCapId, obligationId }) => ({
|
|
538
544
|
id,
|
|
@@ -541,7 +547,7 @@ const selectMarketCaps = (owned, suilendClient) => {
|
|
|
541
547
|
obligationId,
|
|
542
548
|
}))
|
|
543
549
|
: [],
|
|
544
|
-
obligationOwnerCaps: owned.obligationOwnerCaps.filter((ownerCap) => capType(
|
|
550
|
+
obligationOwnerCaps: owned.obligationOwnerCaps.filter((ownerCap) => capType(obligationOwnerCapStruct(), ownerCap.$typeArgs[0]) ===
|
|
545
551
|
obligationOwnerCapType),
|
|
546
552
|
};
|
|
547
553
|
};
|
|
@@ -564,7 +570,7 @@ const parseMarketObligations = (rawObligations, { strategyOwnerCaps, obligationO
|
|
|
564
570
|
};
|
|
565
571
|
};
|
|
566
572
|
export const fetchOwnedObligations = async (suiGrpcClient, address) => {
|
|
567
|
-
const { strategyOwnerCaps, obligationOwnerCaps } = await listOwnedCaps(suiGrpcClient, address,
|
|
573
|
+
const { strategyOwnerCaps, obligationOwnerCaps } = await listOwnedCaps(suiGrpcClient, address, hasStrategyWrapper());
|
|
568
574
|
const lendingMarketTypeByObligationId = new Map();
|
|
569
575
|
for (const { obligationId, lendingMarketType } of [
|
|
570
576
|
...strategyOwnerCaps,
|
|
@@ -3,7 +3,7 @@ import { Transaction, TransactionObjectArgument, TransactionObjectInput, Transac
|
|
|
3
3
|
import BigNumber from "bignumber.js";
|
|
4
4
|
import { ParsedObligation, ParsedReserve } from "../parsers";
|
|
5
5
|
import { RewardsMap, StrategyOwnerCap } from "./types";
|
|
6
|
-
export declare const STRATEGY_WRAPPER_PACKAGE_ID_V1
|
|
6
|
+
export declare const STRATEGY_WRAPPER_PACKAGE_ID_V1: string;
|
|
7
7
|
export declare enum StrategyType {
|
|
8
8
|
sSUI_SUI_LOOPING = "1",
|
|
9
9
|
USDC_sSUI_SUI_LOOPING = "3",
|
package/lib/strategyOwnerCap.js
CHANGED
|
@@ -2,9 +2,11 @@ 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 { getStrategyWrapperPackageId
|
|
5
|
+
import { getStrategyWrapperPackageId } from "../client.js";
|
|
6
|
+
import { SUILEND_MAINNET_NETWORK, getSuilendNetwork } from "../network.js";
|
|
6
7
|
import { Side } from "./types.js";
|
|
7
|
-
|
|
8
|
+
import { cetusInputCoin, cetusTransaction } from "./cetusArguments.js";
|
|
9
|
+
export const STRATEGY_WRAPPER_PACKAGE_ID_V1 = SUILEND_MAINNET_NETWORK.strategyWrapper.typeOriginId;
|
|
8
10
|
export var StrategyType;
|
|
9
11
|
(function (StrategyType) {
|
|
10
12
|
StrategyType["sSUI_SUI_LOOPING"] = "1";
|
|
@@ -21,10 +23,18 @@ export var StrategyType;
|
|
|
21
23
|
StrategyType["USDsui_sSUI_SUI_LOOPING"] = "9";
|
|
22
24
|
StrategyType["stratSUI_SUI_LOOPING"] = "2";
|
|
23
25
|
})(StrategyType || (StrategyType = {}));
|
|
26
|
+
const onMainLendingMarket = (info) => Object.defineProperties(info, {
|
|
27
|
+
lendingMarketId: {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: () => getSuilendNetwork().mainLendingMarket.id,
|
|
30
|
+
},
|
|
31
|
+
lendingMarketType: {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: () => getSuilendNetwork().mainLendingMarket.type,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
24
36
|
export const STRATEGY_TYPE_INFO_MAP = {
|
|
25
|
-
[StrategyType.sSUI_SUI_LOOPING]: {
|
|
26
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
27
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
37
|
+
[StrategyType.sSUI_SUI_LOOPING]: onMainLendingMarket({
|
|
28
38
|
queryParam: "sSUI-SUI-looping",
|
|
29
39
|
header: {
|
|
30
40
|
coinTypes: [NORMALIZED_sSUI_COINTYPE, NORMALIZED_SUI_COINTYPE],
|
|
@@ -37,10 +47,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
37
47
|
borrowCoinType: NORMALIZED_SUI_COINTYPE,
|
|
38
48
|
currencyCoinTypes: [NORMALIZED_SUI_COINTYPE, NORMALIZED_sSUI_COINTYPE],
|
|
39
49
|
defaultCurrencyCoinType: NORMALIZED_SUI_COINTYPE,
|
|
40
|
-
},
|
|
41
|
-
[StrategyType.USDC_sSUI_SUI_LOOPING]: {
|
|
42
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
43
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
50
|
+
}),
|
|
51
|
+
[StrategyType.USDC_sSUI_SUI_LOOPING]: onMainLendingMarket({
|
|
44
52
|
queryParam: "USDC-sSUI-SUI-looping",
|
|
45
53
|
header: {
|
|
46
54
|
coinTypes: [NORMALIZED_USDC_COINTYPE],
|
|
@@ -53,10 +61,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
53
61
|
borrowCoinType: NORMALIZED_SUI_COINTYPE,
|
|
54
62
|
currencyCoinTypes: [NORMALIZED_USDC_COINTYPE],
|
|
55
63
|
defaultCurrencyCoinType: NORMALIZED_USDC_COINTYPE,
|
|
56
|
-
},
|
|
57
|
-
[StrategyType.USDsui_USDC_LOOPING]: {
|
|
58
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
59
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
64
|
+
}),
|
|
65
|
+
[StrategyType.USDsui_USDC_LOOPING]: onMainLendingMarket({
|
|
60
66
|
queryParam: "USDsui-USDC-looping",
|
|
61
67
|
header: {
|
|
62
68
|
coinTypes: [NORMALIZED_USDsui_COINTYPE, NORMALIZED_USDC_COINTYPE],
|
|
@@ -69,7 +75,7 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
69
75
|
borrowCoinType: NORMALIZED_USDC_COINTYPE,
|
|
70
76
|
currencyCoinTypes: [NORMALIZED_USDsui_COINTYPE, NORMALIZED_USDC_COINTYPE],
|
|
71
77
|
defaultCurrencyCoinType: NORMALIZED_USDsui_COINTYPE,
|
|
72
|
-
},
|
|
78
|
+
}),
|
|
73
79
|
[StrategyType.eEARN_USDC_LOOPING]: {
|
|
74
80
|
lendingMarketId: "0x74d92cb095b618f344486f77bcce87fbffc0fe0b46584bb1828bb291a222dda8",
|
|
75
81
|
lendingMarketType: "0x423f05ea163ae1bc5c03d75ef70d3e5d887455084118e46c4f76878530a03619::ember_market::EMBER_MARKET",
|
|
@@ -86,9 +92,7 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
86
92
|
currencyCoinTypes: [NORMALIZED_eEARN_COINTYPE, NORMALIZED_USDC_COINTYPE],
|
|
87
93
|
defaultCurrencyCoinType: NORMALIZED_eEARN_COINTYPE,
|
|
88
94
|
},
|
|
89
|
-
[StrategyType.AUSD_sSUI_SUI_LOOPING]: {
|
|
90
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
91
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
95
|
+
[StrategyType.AUSD_sSUI_SUI_LOOPING]: onMainLendingMarket({
|
|
92
96
|
queryParam: "AUSD-sSUI-SUI-looping",
|
|
93
97
|
header: {
|
|
94
98
|
coinTypes: [NORMALIZED_AUSD_COINTYPE],
|
|
@@ -101,10 +105,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
101
105
|
borrowCoinType: NORMALIZED_SUI_COINTYPE,
|
|
102
106
|
currencyCoinTypes: [NORMALIZED_AUSD_COINTYPE],
|
|
103
107
|
defaultCurrencyCoinType: NORMALIZED_AUSD_COINTYPE,
|
|
104
|
-
},
|
|
105
|
-
[StrategyType.xBTC_sSUI_SUI_LOOPING]: {
|
|
106
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
107
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
108
|
+
}),
|
|
109
|
+
[StrategyType.xBTC_sSUI_SUI_LOOPING]: onMainLendingMarket({
|
|
108
110
|
queryParam: "xBTC-sSUI-SUI-looping",
|
|
109
111
|
header: {
|
|
110
112
|
coinTypes: [NORMALIZED_xBTC_COINTYPE],
|
|
@@ -117,10 +119,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
117
119
|
borrowCoinType: NORMALIZED_SUI_COINTYPE,
|
|
118
120
|
currencyCoinTypes: [NORMALIZED_xBTC_COINTYPE],
|
|
119
121
|
defaultCurrencyCoinType: NORMALIZED_xBTC_COINTYPE,
|
|
120
|
-
},
|
|
121
|
-
[StrategyType.xBTC_suiWBTC_LOOPING]: {
|
|
122
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
123
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
122
|
+
}),
|
|
123
|
+
[StrategyType.xBTC_suiWBTC_LOOPING]: onMainLendingMarket({
|
|
124
124
|
queryParam: "xBTC-suiWBTC-looping",
|
|
125
125
|
header: {
|
|
126
126
|
coinTypes: [NORMALIZED_xBTC_COINTYPE, NORMALIZED_suiWBTC_COINTYPE],
|
|
@@ -133,10 +133,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
133
133
|
borrowCoinType: NORMALIZED_suiWBTC_COINTYPE,
|
|
134
134
|
currencyCoinTypes: [NORMALIZED_xBTC_COINTYPE, NORMALIZED_suiWBTC_COINTYPE],
|
|
135
135
|
defaultCurrencyCoinType: NORMALIZED_xBTC_COINTYPE,
|
|
136
|
-
},
|
|
137
|
-
[StrategyType.suiUSDT_sSUI_SUI_LOOPING]: {
|
|
138
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
139
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
136
|
+
}),
|
|
137
|
+
[StrategyType.suiUSDT_sSUI_SUI_LOOPING]: onMainLendingMarket({
|
|
140
138
|
queryParam: "suiUSDT-sSUI-SUI-looping",
|
|
141
139
|
header: {
|
|
142
140
|
coinTypes: [NORMALIZED_suiUSDT_COINTYPE],
|
|
@@ -149,10 +147,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
149
147
|
borrowCoinType: NORMALIZED_SUI_COINTYPE,
|
|
150
148
|
currencyCoinTypes: [NORMALIZED_suiUSDT_COINTYPE],
|
|
151
149
|
defaultCurrencyCoinType: NORMALIZED_suiUSDT_COINTYPE,
|
|
152
|
-
},
|
|
153
|
-
[StrategyType.AUSD_USDC_LOOPING]: {
|
|
154
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
155
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
150
|
+
}),
|
|
151
|
+
[StrategyType.AUSD_USDC_LOOPING]: onMainLendingMarket({
|
|
156
152
|
queryParam: "AUSD-USDC-looping",
|
|
157
153
|
header: {
|
|
158
154
|
coinTypes: [NORMALIZED_AUSD_COINTYPE, NORMALIZED_USDC_COINTYPE],
|
|
@@ -165,10 +161,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
165
161
|
borrowCoinType: NORMALIZED_USDC_COINTYPE,
|
|
166
162
|
currencyCoinTypes: [NORMALIZED_AUSD_COINTYPE, NORMALIZED_USDC_COINTYPE],
|
|
167
163
|
defaultCurrencyCoinType: NORMALIZED_AUSD_COINTYPE,
|
|
168
|
-
},
|
|
169
|
-
[StrategyType.AUSD_suiUSDT_LOOPING]: {
|
|
170
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
171
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
164
|
+
}),
|
|
165
|
+
[StrategyType.AUSD_suiUSDT_LOOPING]: onMainLendingMarket({
|
|
172
166
|
queryParam: "AUSD-suiUSDT-looping",
|
|
173
167
|
header: {
|
|
174
168
|
coinTypes: [NORMALIZED_AUSD_COINTYPE, NORMALIZED_suiUSDT_COINTYPE],
|
|
@@ -181,10 +175,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
181
175
|
borrowCoinType: NORMALIZED_suiUSDT_COINTYPE,
|
|
182
176
|
currencyCoinTypes: [NORMALIZED_AUSD_COINTYPE, NORMALIZED_suiUSDT_COINTYPE],
|
|
183
177
|
defaultCurrencyCoinType: NORMALIZED_AUSD_COINTYPE,
|
|
184
|
-
},
|
|
185
|
-
[StrategyType.USDC_suiUSDT_LOOPING]: {
|
|
186
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
187
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
178
|
+
}),
|
|
179
|
+
[StrategyType.USDC_suiUSDT_LOOPING]: onMainLendingMarket({
|
|
188
180
|
queryParam: "USDC-suiUSDT-looping",
|
|
189
181
|
header: {
|
|
190
182
|
coinTypes: [NORMALIZED_USDC_COINTYPE, NORMALIZED_suiUSDT_COINTYPE],
|
|
@@ -197,10 +189,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
197
189
|
borrowCoinType: NORMALIZED_suiUSDT_COINTYPE,
|
|
198
190
|
currencyCoinTypes: [NORMALIZED_USDC_COINTYPE, NORMALIZED_suiUSDT_COINTYPE],
|
|
199
191
|
defaultCurrencyCoinType: NORMALIZED_USDC_COINTYPE,
|
|
200
|
-
},
|
|
201
|
-
[StrategyType.USDsui_sSUI_SUI_LOOPING]: {
|
|
202
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
203
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
192
|
+
}),
|
|
193
|
+
[StrategyType.USDsui_sSUI_SUI_LOOPING]: onMainLendingMarket({
|
|
204
194
|
queryParam: "USDsui-sSUI-SUI-looping",
|
|
205
195
|
header: {
|
|
206
196
|
coinTypes: [NORMALIZED_USDsui_COINTYPE],
|
|
@@ -213,10 +203,8 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
213
203
|
borrowCoinType: NORMALIZED_SUI_COINTYPE,
|
|
214
204
|
currencyCoinTypes: [NORMALIZED_USDsui_COINTYPE],
|
|
215
205
|
defaultCurrencyCoinType: NORMALIZED_USDsui_COINTYPE,
|
|
216
|
-
},
|
|
217
|
-
[StrategyType.stratSUI_SUI_LOOPING]: {
|
|
218
|
-
lendingMarketId: LENDING_MARKET_ID,
|
|
219
|
-
lendingMarketType: LENDING_MARKET_TYPE,
|
|
206
|
+
}),
|
|
207
|
+
[StrategyType.stratSUI_SUI_LOOPING]: onMainLendingMarket({
|
|
220
208
|
queryParam: "stratSUI-SUI-looping",
|
|
221
209
|
header: {
|
|
222
210
|
coinTypes: [NORMALIZED_stratSUI_COINTYPE, NORMALIZED_SUI_COINTYPE],
|
|
@@ -229,7 +217,7 @@ export const STRATEGY_TYPE_INFO_MAP = {
|
|
|
229
217
|
borrowCoinType: NORMALIZED_SUI_COINTYPE,
|
|
230
218
|
currencyCoinTypes: [NORMALIZED_SUI_COINTYPE, NORMALIZED_stratSUI_COINTYPE],
|
|
231
219
|
defaultCurrencyCoinType: NORMALIZED_SUI_COINTYPE,
|
|
232
|
-
},
|
|
220
|
+
}),
|
|
233
221
|
};
|
|
234
222
|
const getStrategyLendingMarket = (strategyType) => {
|
|
235
223
|
const info = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
@@ -398,9 +386,9 @@ depositReserve, strategyOwnerCap, transaction) => {
|
|
|
398
386
|
try {
|
|
399
387
|
coinOut = (await cetusSdk.fixableRouterSwapV3({
|
|
400
388
|
router: routers,
|
|
401
|
-
inputCoin: coinIn,
|
|
389
|
+
inputCoin: cetusInputCoin(coinIn),
|
|
402
390
|
slippage: 3 / 100,
|
|
403
|
-
txb: transaction,
|
|
391
|
+
txb: cetusTransaction(transaction),
|
|
404
392
|
partner: cetusPartnerId,
|
|
405
393
|
}));
|
|
406
394
|
}
|
package/network.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type EnvConfig } from "./_generated/_envs";
|
|
2
|
+
export type StrategyWrapperNetwork = {
|
|
3
|
+
upgradeCapId: string;
|
|
4
|
+
typeOriginId: string;
|
|
5
|
+
defaultPackageId: string;
|
|
6
|
+
packageIdByMarketVersion: ReadonlyMap<bigint, string>;
|
|
7
|
+
};
|
|
8
|
+
export type SuilendNetwork = {
|
|
9
|
+
name: string;
|
|
10
|
+
env: EnvConfig;
|
|
11
|
+
mainLendingMarket: {
|
|
12
|
+
id: string;
|
|
13
|
+
type: string;
|
|
14
|
+
};
|
|
15
|
+
suilendUpgradeCapId: string;
|
|
16
|
+
latestMarketVersion: bigint;
|
|
17
|
+
publishedAtByMarketVersion: ReadonlyMap<bigint, string>;
|
|
18
|
+
strategyWrapper?: StrategyWrapperNetwork;
|
|
19
|
+
pythStateId: string;
|
|
20
|
+
wormholeStateId: string;
|
|
21
|
+
};
|
|
22
|
+
export declare const SUILEND_MAINNET_NETWORK: SuilendNetwork;
|
|
23
|
+
export declare const getSuilendNetwork: () => SuilendNetwork;
|
|
24
|
+
export declare const isSameSuilendNetwork: (a: SuilendNetwork, b: SuilendNetwork) => boolean;
|
|
25
|
+
export declare function setSuilendNetwork(next: SuilendNetwork): void;
|
|
26
|
+
export declare function getStrategyWrapperNetwork(): StrategyWrapperNetwork;
|
|
27
|
+
export declare function setPublishedAt(publishedAt: string): void;
|
package/network.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getOriginalId, getPublishedAt, mainnetEnv, setActiveEnv, } from "./_generated/_envs/index.js";
|
|
2
|
+
import { registerEnv } from "./_generated/_framework/env.js";
|
|
3
|
+
const STRATEGY_WRAPPER_PACKAGE_ID_V7 = "0x864b66441e95323c320ee7584592769930a2d236b45d731011ee7a98eb785b35";
|
|
4
|
+
export const SUILEND_MAINNET_NETWORK = Object.freeze({
|
|
5
|
+
name: "mainnet",
|
|
6
|
+
env: mainnetEnv,
|
|
7
|
+
mainLendingMarket: Object.freeze({
|
|
8
|
+
id: "0x84030d26d85eaa7035084a057f2f11f701b7e2e4eda87551becbc7c97505ece1",
|
|
9
|
+
type: "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf::suilend::MAIN_POOL",
|
|
10
|
+
}),
|
|
11
|
+
suilendUpgradeCapId: "0x3d4ef1859c3ee9fc72858f588b56a09da5466e64f8cc4e90a7b3b909fba8a7ae",
|
|
12
|
+
latestMarketVersion: BigInt(8),
|
|
13
|
+
publishedAtByMarketVersion: new Map([
|
|
14
|
+
[
|
|
15
|
+
BigInt(7),
|
|
16
|
+
"0x59672975e15c58ffc9450f5236b6aa9fa2407d94b8081e634778aa01957d8c6f",
|
|
17
|
+
],
|
|
18
|
+
]),
|
|
19
|
+
strategyWrapper: Object.freeze({
|
|
20
|
+
upgradeCapId: "0x486ef016bd357fadf981aba35a6c31df8d4c0c4136b2e78fdda87cb2832f3033",
|
|
21
|
+
typeOriginId: "0xba97dc73a07638d03d77ad2161484eb21db577edc9cadcd7035fef4b4f2f6fa1",
|
|
22
|
+
defaultPackageId: STRATEGY_WRAPPER_PACKAGE_ID_V7,
|
|
23
|
+
packageIdByMarketVersion: new Map([
|
|
24
|
+
[BigInt(7), STRATEGY_WRAPPER_PACKAGE_ID_V7],
|
|
25
|
+
]),
|
|
26
|
+
}),
|
|
27
|
+
pythStateId: "0x03719fae774ddab3cfcaa53bbc046f0cbe21410019b6280811bf3f9f4b05839d",
|
|
28
|
+
wormholeStateId: "0xdbca52b9fb4f712e25f61f974586d93ac541bcf8389564f0323bb07215168b5c",
|
|
29
|
+
});
|
|
30
|
+
let network = SUILEND_MAINNET_NETWORK;
|
|
31
|
+
let publishedAtOverride;
|
|
32
|
+
export const getSuilendNetwork = () => network;
|
|
33
|
+
export const isSameSuilendNetwork = (a, b) => a === b ||
|
|
34
|
+
(a.name === b.name &&
|
|
35
|
+
a.suilendUpgradeCapId === b.suilendUpgradeCapId &&
|
|
36
|
+
a.strategyWrapper?.upgradeCapId === b.strategyWrapper?.upgradeCapId &&
|
|
37
|
+
getOriginalId("suilend", a.env) === getOriginalId("suilend", b.env) &&
|
|
38
|
+
getPublishedAt("suilend", a.env) === getPublishedAt("suilend", b.env));
|
|
39
|
+
export function setSuilendNetwork(next) {
|
|
40
|
+
if (next.name === SUILEND_MAINNET_NETWORK.name &&
|
|
41
|
+
next.env !== SUILEND_MAINNET_NETWORK.env)
|
|
42
|
+
throw new Error(`setSuilendNetwork: the name "${next.name}" belongs to the generated mainnet env. Give this network another name.`);
|
|
43
|
+
if (publishedAtOverride &&
|
|
44
|
+
!isSameSuilendNetwork(publishedAtOverride.network, next))
|
|
45
|
+
publishedAtOverride = undefined;
|
|
46
|
+
registerEnv(next.name, next.env);
|
|
47
|
+
setActiveEnv(next.name, publishedAtOverride && { suilend: publishedAtOverride.id });
|
|
48
|
+
network = next;
|
|
49
|
+
}
|
|
50
|
+
export function getStrategyWrapperNetwork() {
|
|
51
|
+
const { name, strategyWrapper } = network;
|
|
52
|
+
if (!strategyWrapper)
|
|
53
|
+
throw new Error(`strategy_wrapper is not deployed on the ${name} network.`);
|
|
54
|
+
return strategyWrapper;
|
|
55
|
+
}
|
|
56
|
+
export function setPublishedAt(publishedAt) {
|
|
57
|
+
publishedAtOverride = { network, id: publishedAt };
|
|
58
|
+
setActiveEnv(network.name, { suilend: publishedAt });
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@suilend/sdk","version":"14.
|
|
1
|
+
{"name":"@suilend/sdk","version":"14.3.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","./network":"./network.js","./strategies":"./strategies.js","./api/events":"./api/events.js","./api":"./api/index.js","./lib/cetusArguments":"./lib/cetusArguments.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","./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":{"@cetusprotocol/aggregator-sdk":"1.7.5","@flowx-finance/sdk":"2.1.0","@pythnetwork/hermes-client":"3.1.0","@pythnetwork/pyth-sui-js":"4.0.0","@suilend/springsui-sdk":"5.0.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.3"},"devDependencies":{"@mysten/bcs":"2.1.3","@mysten/sui":"2.37.0","@suilend/sui-core":"2.3.0","@tsconfig/recommended":"1.0.13","@types/bn.js":"5.2.0","@types/lodash":"4.17.27","@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.5","vitest":"5.0.5"},"peerDependencies":{"@mysten/bcs":"^2.1.1","@mysten/sui":">=2.31.3 <3","@suilend/sui-core":"^2.3.0"},"type":"module"}
|
package/strategies.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { SuiGrpcClient } from "@mysten/sui/grpc";
|
|
|
4
4
|
import { Transaction, TransactionArgument, TransactionObjectArgument, TransactionObjectInput } from "@mysten/sui/transactions";
|
|
5
5
|
import BigNumber from "bignumber.js";
|
|
6
6
|
import { LstClient } from "@suilend/springsui-sdk";
|
|
7
|
-
import { LiquidStakingInfo } from "@suilend/springsui-sdk/_generated/
|
|
7
|
+
import { LiquidStakingInfo } from "@suilend/springsui-sdk/_generated/liquid-staking/liquid-staking/structs";
|
|
8
8
|
import { SuilendClient } from "./client";
|
|
9
9
|
import { RewardsMap } from "./lib";
|
|
10
10
|
import { RewardMap } from "./lib/liquidityMining";
|
package/strategies.js
CHANGED
|
@@ -4,13 +4,14 @@ import { SUI_DECIMALS } from "@mysten/sui/utils";
|
|
|
4
4
|
import BigNumber from "bignumber.js";
|
|
5
5
|
import { BN } from "bn.js";
|
|
6
6
|
import cloneDeep from "lodash/cloneDeep.js";
|
|
7
|
-
import { LstClient,
|
|
8
|
-
import {
|
|
7
|
+
import { LstClient, getLatestPackageId as getLatestSpringSuiPackageId, getSpringSuiNetwork, } from "@suilend/springsui-sdk";
|
|
8
|
+
import { MAX_U64, MS_PER_YEAR, NORMALIZED_AUSD_COINTYPE, NORMALIZED_SUI_COINTYPE, NORMALIZED_USDC_COINTYPE, NORMALIZED_sSUI_COINTYPE, NORMALIZED_suiUSDT_COINTYPE, NORMALIZED_suiWBTC_COINTYPE, NORMALIZED_xBTC_COINTYPE, assertResponseOk, getApiUrl, getSpendableCoin, isSui, } from "@suilend/sui-core";
|
|
9
9
|
import { getNetAprPercent } from "./lib/index.js";
|
|
10
10
|
import { getRewardsMap } from "./lib/liquidityMining.js";
|
|
11
11
|
import { STRATEGY_TYPE_INFO_MAP, StrategyType, strategyBorrow, strategyClaimRewardsAndMergeCoins, strategyDeposit, strategyWithdraw, } from "./lib/strategyOwnerCap.js";
|
|
12
12
|
import { MMT_CONTRACT_PACKAGE_ID, MMT_VERSION_OBJECT_ID } from "./mmt.js";
|
|
13
13
|
import { bisectionMethod, getWeightedBorrowsUsd } from "./utils/index.js";
|
|
14
|
+
import { cetusInputCoin, cetusTransaction } from "./lib/cetusArguments.js";
|
|
14
15
|
export const STRATEGY_E = 10 ** -7;
|
|
15
16
|
export const STRATEGY_FLASH_REPAY_MAX_RESIDUAL_USD = 0.1;
|
|
16
17
|
export const STRATEGY_RATE_LIMITED_ERROR_MESSAGE = "This withdrawal exceeds the lending market's outflow limit for now. Withdraw a smaller amount, or wait and try again.";
|
|
@@ -314,14 +315,13 @@ export const fetchStrategyLstMap = async (suiGrpcClient) => {
|
|
|
314
315
|
// LSTs that will be/are/have been used as rewards
|
|
315
316
|
NORMALIZED_sSUI_COINTYPE,
|
|
316
317
|
]));
|
|
317
|
-
const publishedAt = await getLatestSpringSuiPackageId(suiGrpcClient,
|
|
318
|
-
const lstInfoUrl = `${
|
|
318
|
+
const publishedAt = await getLatestSpringSuiPackageId(suiGrpcClient, getSpringSuiNetwork().upgradeCapId);
|
|
319
|
+
const lstInfoUrl = `${getApiUrl()}/springsui/lst-info?${new URLSearchParams({
|
|
319
320
|
coinTypes: lstCoinTypes.join(","),
|
|
320
321
|
})}`;
|
|
321
322
|
const lstInfoRes = await fetch(lstInfoUrl);
|
|
323
|
+
assertResponseOk(lstInfoRes, "LST info request");
|
|
322
324
|
const lstInfoJson = await lstInfoRes.json();
|
|
323
|
-
if (lstInfoRes?.statusCode === 500)
|
|
324
|
-
throw new Error("Failed to fetch LST info");
|
|
325
325
|
const lstInfoMap = Object.fromEntries(Object.entries(lstInfoJson).map(([lstCoinType, lstInfo]) => {
|
|
326
326
|
return [lstCoinType, lstInfo];
|
|
327
327
|
}));
|
|
@@ -332,10 +332,9 @@ export const fetchStrategyLstMap = async (suiGrpcClient) => {
|
|
|
332
332
|
0).div(100);
|
|
333
333
|
const redeemFeePercent = new BigNumber(lstInfo.liquidStakingInfo.feeConfig.element?.redeemFeeBps.toString() ??
|
|
334
334
|
0).div(100);
|
|
335
|
-
const res = await fetch(`${
|
|
335
|
+
const res = await fetch(`${getApiUrl()}/springsui/historical-rates?coinType=${lstCoinType}×tamps=${Math.floor(Date.now() / 1000)}`);
|
|
336
|
+
assertResponseOk(res, `Historical LST to SUI exchange rates request for ${lstCoinType}`);
|
|
336
337
|
const json = await res.json();
|
|
337
|
-
if (json?.statusCode === 500)
|
|
338
|
-
throw new Error(`Failed to fetch historical LST to SUI exchange rates for ${lstCoinType}`);
|
|
339
338
|
const suiToLstExchangeRate = !new BigNumber(json[0].value).eq(0)
|
|
340
339
|
? new BigNumber(1).div(new BigNumber(json[0].value))
|
|
341
340
|
: new BigNumber(1);
|
|
@@ -888,11 +887,10 @@ lstMap, strategyType, _deposits, _borrowedAmount, deposit, targetExposure) => {
|
|
|
888
887
|
// Stats - Global TVL
|
|
889
888
|
export const fetchStrategyGlobalTvlAmountUsdMap = async () => {
|
|
890
889
|
try {
|
|
891
|
-
const url = `${
|
|
890
|
+
const url = `${getApiUrl()}/strategies/tvl`;
|
|
892
891
|
const res = await fetch(url);
|
|
892
|
+
assertResponseOk(res, "Strategies TVL request");
|
|
893
893
|
const json = await res.json();
|
|
894
|
-
if (json?.statusCode === 500)
|
|
895
|
-
throw new Error("Failed to fetch Strategies TVL");
|
|
896
894
|
const result = Object.values(StrategyType).reduce((acc, strategyType) => {
|
|
897
895
|
const entry = json.strategies.find((s) => `${s.strategyType}` === strategyType);
|
|
898
896
|
const tvlUsd = entry
|
|
@@ -1246,7 +1244,7 @@ transaction) => {
|
|
|
1246
1244
|
router: routers,
|
|
1247
1245
|
inputCoin: stepBorrowedCoin,
|
|
1248
1246
|
slippage: slippagePercent / 100,
|
|
1249
|
-
txb: transaction,
|
|
1247
|
+
txb: cetusTransaction(transaction),
|
|
1250
1248
|
partner: cetusPartnerId,
|
|
1251
1249
|
}));
|
|
1252
1250
|
}
|
|
@@ -1397,7 +1395,7 @@ dryRunTransaction) => {
|
|
|
1397
1395
|
router: routers,
|
|
1398
1396
|
inputCoin: stepWithdrawnCoin,
|
|
1399
1397
|
slippage: slippagePercent / 100,
|
|
1400
|
-
txb: transaction,
|
|
1398
|
+
txb: cetusTransaction(transaction),
|
|
1401
1399
|
partner: cetusPartnerId,
|
|
1402
1400
|
}));
|
|
1403
1401
|
const txCopy = Transaction.from(transaction);
|
|
@@ -1563,7 +1561,7 @@ dryRunTransaction) => {
|
|
|
1563
1561
|
router: routers,
|
|
1564
1562
|
inputCoin: withdrawnRemainingLstCoin,
|
|
1565
1563
|
slippage: 100 / 100,
|
|
1566
|
-
txb: transaction,
|
|
1564
|
+
txb: cetusTransaction(transaction),
|
|
1567
1565
|
partner: cetusPartnerId,
|
|
1568
1566
|
}));
|
|
1569
1567
|
}
|
|
@@ -1695,7 +1693,7 @@ dryRunTransaction) => {
|
|
|
1695
1693
|
router: routers,
|
|
1696
1694
|
inputCoin: withdrawnBaseCoin,
|
|
1697
1695
|
slippage: fullRepaySlippagePercent / 100,
|
|
1698
|
-
txb: transaction,
|
|
1696
|
+
txb: cetusTransaction(transaction),
|
|
1699
1697
|
partner: cetusPartnerId,
|
|
1700
1698
|
}));
|
|
1701
1699
|
}
|
|
@@ -2065,7 +2063,7 @@ dryRunTransaction) => {
|
|
|
2065
2063
|
router: routers,
|
|
2066
2064
|
inputCoin: stepWithdrawnCoin,
|
|
2067
2065
|
slippage: slippagePercent / 100,
|
|
2068
|
-
txb: transaction,
|
|
2066
|
+
txb: cetusTransaction(transaction),
|
|
2069
2067
|
partner: cetusPartnerId,
|
|
2070
2068
|
}));
|
|
2071
2069
|
}
|
|
@@ -2272,9 +2270,9 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2272
2270
|
try {
|
|
2273
2271
|
baseCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
2274
2272
|
router: routers,
|
|
2275
|
-
inputCoin: otherCoin,
|
|
2273
|
+
inputCoin: cetusInputCoin(otherCoin),
|
|
2276
2274
|
slippage: slippagePercent / 100,
|
|
2277
|
-
txb: transaction,
|
|
2275
|
+
txb: cetusTransaction(transaction),
|
|
2278
2276
|
partner: cetusPartnerId,
|
|
2279
2277
|
}));
|
|
2280
2278
|
}
|
|
@@ -2421,7 +2419,7 @@ const swapStrategyWithdrawnCoin = async (cetusSdk, cetusPartnerId, transaction,
|
|
|
2421
2419
|
router: routers,
|
|
2422
2420
|
inputCoin: coin,
|
|
2423
2421
|
slippage: slippagePercent / 100,
|
|
2424
|
-
txb: swapTransaction,
|
|
2422
|
+
txb: cetusTransaction(swapTransaction),
|
|
2425
2423
|
partner: cetusPartnerId,
|
|
2426
2424
|
}));
|
|
2427
2425
|
return {
|
|
@@ -2693,7 +2691,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2693
2691
|
router: routers,
|
|
2694
2692
|
inputCoin: withdrawnCoin,
|
|
2695
2693
|
slippage: slippagePercent / 100,
|
|
2696
|
-
txb: transaction,
|
|
2694
|
+
txb: cetusTransaction(transaction),
|
|
2697
2695
|
partner: cetusPartnerId,
|
|
2698
2696
|
}));
|
|
2699
2697
|
}
|
|
@@ -2944,7 +2942,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2944
2942
|
router: routers,
|
|
2945
2943
|
inputCoin: withdrawnCoin,
|
|
2946
2944
|
slippage: slippagePercent / 100,
|
|
2947
|
-
txb: transaction,
|
|
2945
|
+
txb: cetusTransaction(transaction),
|
|
2948
2946
|
partner: cetusPartnerId,
|
|
2949
2947
|
}));
|
|
2950
2948
|
}
|
|
@@ -3144,7 +3142,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
3144
3142
|
router: routers,
|
|
3145
3143
|
inputCoin: flashLoanBorrowedCoin,
|
|
3146
3144
|
slippage: adjustRepaySlippagePercent / 100,
|
|
3147
|
-
txb: transaction,
|
|
3145
|
+
txb: cetusTransaction(transaction),
|
|
3148
3146
|
partner: cetusPartnerId,
|
|
3149
3147
|
}));
|
|
3150
3148
|
}
|
|
@@ -3213,9 +3211,9 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
3213
3211
|
try {
|
|
3214
3212
|
flashLoanRepayCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
3215
3213
|
router: repayRouters,
|
|
3216
|
-
inputCoin: flashLoanRepayCoin,
|
|
3214
|
+
inputCoin: cetusInputCoin(flashLoanRepayCoin),
|
|
3217
3215
|
slippage: repayLegSlippagePercent / 100,
|
|
3218
|
-
txb: transaction,
|
|
3216
|
+
txb: cetusTransaction(transaction),
|
|
3219
3217
|
partner: cetusPartnerId,
|
|
3220
3218
|
}));
|
|
3221
3219
|
}
|
|
@@ -3365,7 +3363,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
3365
3363
|
router: depositRouters,
|
|
3366
3364
|
inputCoin: flashLoanBorrowedCoin,
|
|
3367
3365
|
slippage: depositLegSlippagePercent / 100,
|
|
3368
|
-
txb: transaction,
|
|
3366
|
+
txb: cetusTransaction(transaction),
|
|
3369
3367
|
partner: cetusPartnerId,
|
|
3370
3368
|
}));
|
|
3371
3369
|
}
|
|
@@ -3441,9 +3439,9 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
3441
3439
|
try {
|
|
3442
3440
|
flashLoanRepayCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
3443
3441
|
router: repayRouters,
|
|
3444
|
-
inputCoin: flashLoanRepayCoin,
|
|
3442
|
+
inputCoin: cetusInputCoin(flashLoanRepayCoin),
|
|
3445
3443
|
slippage: repayLegSlippagePercent / 100,
|
|
3446
|
-
txb: transaction,
|
|
3444
|
+
txb: cetusTransaction(transaction),
|
|
3447
3445
|
partner: cetusPartnerId,
|
|
3448
3446
|
}));
|
|
3449
3447
|
}
|
package/swap/transaction.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getSpendableCoin } from "@suilend/sui-core";
|
|
2
2
|
import { QuoteProvider } from "./quote.js";
|
|
3
|
+
import { cetusInputCoin, cetusTransaction } from "../lib/cetusArguments.js";
|
|
3
4
|
const getSwapTransactionWrapper = async (provider, getSwapTransaction) => {
|
|
4
5
|
console.log(`[getSwapTransactionWrapper] fetching transaction for ${provider} quote`);
|
|
5
6
|
try {
|
|
@@ -20,13 +21,13 @@ export const getSwapTransaction = async (suiGrpcClient, address, quote, slippage
|
|
|
20
21
|
}
|
|
21
22
|
const coinOut = await sdkMap[QuoteProvider.CETUS].routerSwap({
|
|
22
23
|
router: quote.quote,
|
|
23
|
-
inputCoin: coinIn,
|
|
24
|
+
inputCoin: cetusInputCoin(coinIn),
|
|
24
25
|
slippage: slippagePercent / 100,
|
|
25
|
-
txb: transaction,
|
|
26
|
+
txb: cetusTransaction(transaction),
|
|
26
27
|
partner: partnerIdMap[QuoteProvider.CETUS],
|
|
27
28
|
});
|
|
28
29
|
return {
|
|
29
|
-
transaction
|
|
30
|
+
transaction,
|
|
30
31
|
coinOut: coinOut,
|
|
31
32
|
};
|
|
32
33
|
});
|
|
@@ -57,7 +58,7 @@ export const getSwapTransaction = async (suiGrpcClient, address, quote, slippage
|
|
|
57
58
|
.commission(new FlowXCommission(partnerIdMap[QuoteProvider.FLOWX], new FlowXCoin(quote.out.coinType), FlowXCommissionType.PERCENTAGE, 0, false))
|
|
58
59
|
.build();
|
|
59
60
|
const coinOut = await trade.swap({
|
|
60
|
-
coinIn
|
|
61
|
+
coinIn,
|
|
61
62
|
client: suiGrpcClient,
|
|
62
63
|
tx: transaction,
|
|
63
64
|
});
|
package/utils/obligation.js
CHANGED
|
@@ -2,9 +2,8 @@ import { normalizeSuiAddress } from "@mysten/sui/utils";
|
|
|
2
2
|
import { BigNumber } from "bignumber.js";
|
|
3
3
|
import pLimit from "p-limit";
|
|
4
4
|
import { phantom } from "../_generated/_framework/reified.js";
|
|
5
|
-
import {
|
|
5
|
+
import { getOriginalId } from "../_generated/_envs/index.js";
|
|
6
6
|
import { Obligation } from "../_generated/suilend/obligation/structs.js";
|
|
7
|
-
const NORMALIZED_PACKAGE_ID = normalizeSuiAddress(PACKAGE_ID);
|
|
8
7
|
export async function fetchAllObligationsForMarketWithHandler(suiGrpcClient, lendingMarketId, lendingMarketType, chunkHandler) {
|
|
9
8
|
const limit = pLimit(30);
|
|
10
9
|
const { object: rawLendingMarket } = await suiGrpcClient.getObject({
|
|
@@ -150,9 +149,11 @@ export async function getObligationHistoryPage(suiGraphQLClient, obligationId, m
|
|
|
150
149
|
return { cursor: null, history: [] };
|
|
151
150
|
}
|
|
152
151
|
let formattedEvents = [];
|
|
152
|
+
const packageId = getOriginalId("suilend");
|
|
153
|
+
const normalizedPackageId = normalizeSuiAddress(packageId);
|
|
153
154
|
for (const txNode of payload.nodes) {
|
|
154
|
-
const events = txNode.effects.events.nodes.filter((e) => e.contents?.type.repr.startsWith(`${
|
|
155
|
-
e.contents?.type.repr.startsWith(`${
|
|
155
|
+
const events = txNode.effects.events.nodes.filter((e) => e.contents?.type.repr.startsWith(`${packageId}::`) ||
|
|
156
|
+
e.contents?.type.repr.startsWith(`${normalizedPackageId}::`));
|
|
156
157
|
formattedEvents = formattedEvents.concat(formatEventsToHistory(obligationId, txNode, events));
|
|
157
158
|
}
|
|
158
159
|
return {
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare const PACKAGE_ID = "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf";
|
|
2
|
-
export declare const PKG_V1 = "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf";
|
|
3
|
-
export declare const PKG_V8 = "0x5b54b47971238403d6ade3c8c2cc75814cb55145a5184af916bb5b12aaf184cb";
|
|
4
|
-
export declare const PKG_V10 = "0xe37cc7bb50fd9b6dbd3873df66fa2c554e973697f50ef97707311dc78bd08444";
|
|
5
|
-
export declare const PKG_V11 = "0xd2a67633ccb8de063163e25bcfca242929caf5cf1a26c2929dab519ee0b8f331";
|
|
6
|
-
export declare function setPublishedAt(publishedAt: string): void;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { setActiveEnv } from "../_envs/index.js";
|
|
2
|
-
export const PACKAGE_ID = "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf";
|
|
3
|
-
export const PKG_V1 = "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf";
|
|
4
|
-
export const PKG_V8 = "0x5b54b47971238403d6ade3c8c2cc75814cb55145a5184af916bb5b12aaf184cb";
|
|
5
|
-
export const PKG_V10 = "0xe37cc7bb50fd9b6dbd3873df66fa2c554e973697f50ef97707311dc78bd08444";
|
|
6
|
-
export const PKG_V11 = "0xd2a67633ccb8de063163e25bcfca242929caf5cf1a26c2929dab519ee0b8f331";
|
|
7
|
-
// Hand-maintained: sui-client-gen does not emit this file, and a run with its
|
|
8
|
-
// clean option would delete it. Generated calls resolve their target through
|
|
9
|
-
// getPublishedAt, so the override has to go through setActiveEnv as well.
|
|
10
|
-
export function setPublishedAt(publishedAt) {
|
|
11
|
-
setActiveEnv("mainnet", { suilend: publishedAt });
|
|
12
|
-
}
|