@suilend/sdk 5.0.0 → 5.1.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 +21 -0
- package/client.js +149 -28
- package/lib/initialize.js +7 -5
- package/package.json +1 -1
- package/utils/obligation.d.ts +4 -0
- package/utils/obligation.js +1 -1
package/client.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SuiClientTypes } from "@mysten/sui/client";
|
|
1
2
|
import { SuiGrpcClient } from "@mysten/sui/grpc";
|
|
2
3
|
import { Transaction, TransactionObjectArgument, TransactionObjectInput } from "@mysten/sui/transactions";
|
|
3
4
|
import { SuiPriceServiceConnection, SuiPythClient } from "@pythnetwork/pyth-sui-js";
|
|
@@ -10,6 +11,17 @@ export declare const ADMIN_ADDRESS: string;
|
|
|
10
11
|
export declare const LENDING_MARKET_REGISTRY_ID: string;
|
|
11
12
|
export declare const LENDING_MARKET_ID: string, LENDING_MARKET_TYPE: string;
|
|
12
13
|
export declare const STEAMM_LM_LENDING_MARKET_ID: string, STEAMM_LM_LENDING_MARKET_TYPE: string;
|
|
14
|
+
export declare function getLatestPackageId(suiGrpcClient: SuiGrpcClient, upgradeCapId: string): Promise<any>;
|
|
15
|
+
/**
|
|
16
|
+
* Lists every owned object of `type`, following pagination.
|
|
17
|
+
*
|
|
18
|
+
* `object_type` matches all instantiations when the type params are omitted
|
|
19
|
+
* (`0x2::coin::Coin` returns every `Coin<T>`), so passing a bare struct type
|
|
20
|
+
* lets one request serve callers that each only want their own type args.
|
|
21
|
+
* Filter the result on `obj.type` — comparing via normalizeStructTag, since
|
|
22
|
+
* the node returns fully-normalized addresses.
|
|
23
|
+
*/
|
|
24
|
+
export declare function listAllOwnedObjects<Include extends SuiClientTypes.ObjectInclude>(suiGrpcClient: SuiGrpcClient, owner: string, type: string, include?: Include): Promise<SuiClientTypes.Object<Include>[]>;
|
|
13
25
|
export type ObligationWithUnclaimedRewards = {
|
|
14
26
|
id: string;
|
|
15
27
|
lendingMarketId?: string;
|
|
@@ -34,6 +46,14 @@ export declare class SuilendClient {
|
|
|
34
46
|
pythConnection: SuiPriceServiceConnection;
|
|
35
47
|
constructor(lendingMarket: LendingMarket<string>, suiGrpcClient: SuiGrpcClient);
|
|
36
48
|
static initialize(lendingMarketId: string, lendingMarketType: string, suiGrpcClient: SuiGrpcClient, logPackageId?: boolean): Promise<SuilendClient>;
|
|
49
|
+
/**
|
|
50
|
+
* Same as `initialize`, but fetches every LendingMarket object in one
|
|
51
|
+
* request rather than one per market.
|
|
52
|
+
*/
|
|
53
|
+
static initializeAll(lendingMarkets: {
|
|
54
|
+
id: string;
|
|
55
|
+
type: string;
|
|
56
|
+
}[], suiGrpcClient: SuiGrpcClient, logPackageId?: boolean): Promise<SuilendClient[]>;
|
|
37
57
|
static getFeeReceivers(suiGrpcClient: SuiGrpcClient, lendingMarketId: string): Promise<{
|
|
38
58
|
receivers: string[];
|
|
39
59
|
weights: string[];
|
|
@@ -44,6 +64,7 @@ export declare class SuilendClient {
|
|
|
44
64
|
};
|
|
45
65
|
static getObligationOwnerCaps(ownerId: string, lendingMarketTypeArgs: string[], suiGrpcClient: SuiGrpcClient): Promise<ObligationOwnerCap<string>[]>;
|
|
46
66
|
static getObligation(obligationId: string, lendingMarketTypeArgs: string[], suiGrpcClient: SuiGrpcClient): Promise<Obligation<string>>;
|
|
67
|
+
static getObligations(obligationIds: string[], lendingMarketTypeArgs: string[], suiGrpcClient: SuiGrpcClient): Promise<Obligation<string>[]>;
|
|
47
68
|
getObligation(obligationId: string): Promise<Obligation<string>>;
|
|
48
69
|
static getLendingMarketOwnerCapId(ownerId: string, lendingMarketTypeArgs: string[], suiGrpcClient: SuiGrpcClient): Promise<string | undefined>;
|
|
49
70
|
getLendingMarketOwnerCapId(ownerId: string): Promise<string | undefined>;
|
package/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SUI_CLOCK_OBJECT_ID, SUI_SYSTEM_STATE_OBJECT_ID, normalizeStructTag, toHex, } from "@mysten/sui/utils";
|
|
1
|
+
import { SUI_CLOCK_OBJECT_ID, SUI_SYSTEM_STATE_OBJECT_ID, normalizeStructTag, normalizeSuiObjectId, toHex, } from "@mysten/sui/utils";
|
|
2
2
|
import { SuiPriceServiceConnection, SuiPythClient, } from "@pythnetwork/pyth-sui-js";
|
|
3
3
|
import { extractCTokenCoinType, getAllCoins, getSpendableCoin, } from "@suilend/sui-core";
|
|
4
4
|
import { PriceInfoObject } from "./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-info/structs.js";
|
|
@@ -14,6 +14,7 @@ import { createReserveConfig, } from "./_generated/suilend/reserve-config/functi
|
|
|
14
14
|
import { PRIMARY_PYTH_ENDPOINT } from "./lib/pyth.js";
|
|
15
15
|
import { createJsonRpcAdapter } from "./lib/pythAdapter.js";
|
|
16
16
|
import { Side } from "./lib/types.js";
|
|
17
|
+
import { chunkedMultiGet } from "./utils/obligation.js";
|
|
17
18
|
const SUI_COINTYPE = "0x2::sui::SUI";
|
|
18
19
|
const NORMALIZED_SUI_COINTYPE = normalizeStructTag(SUI_COINTYPE);
|
|
19
20
|
const isSui = (coinType) => normalizeStructTag(coinType) === NORMALIZED_SUI_COINTYPE;
|
|
@@ -46,12 +47,86 @@ export const [STEAMM_LM_LENDING_MARKET_ID, STEAMM_LM_LENDING_MARKET_TYPE] = proc
|
|
|
46
47
|
"0xc1888ec1b81a414e427a44829310508352aec38252ee0daa9f8b181b6947de9f",
|
|
47
48
|
"0x0a071f4976abae1a7f722199cf0bfcbe695ef9408a878e7d12a7ca87b7e582a6::lp_rewards::LP_REWARDS",
|
|
48
49
|
];
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
// Keyed by upgradeCapId. Only dedupes calls that are still in flight — e.g.
|
|
51
|
+
// initializing N lending markets at once each calling SuilendClient.initialize()
|
|
52
|
+
// with the same upgrade cap. Deliberately not cached past settlement: this
|
|
53
|
+
// runs on long-running indexer processes, and caching a success forever would
|
|
54
|
+
// mean a real on-chain package upgrade is never picked up without a restart;
|
|
55
|
+
// caching a failure forever would permanently break initialize() for one
|
|
56
|
+
// transient RPC error.
|
|
57
|
+
const latestPackageIdCache = new Map();
|
|
58
|
+
export async function getLatestPackageId(suiGrpcClient, upgradeCapId) {
|
|
59
|
+
const cached = latestPackageIdCache.get(upgradeCapId);
|
|
60
|
+
if (cached)
|
|
61
|
+
return cached;
|
|
62
|
+
const promise = suiGrpcClient
|
|
63
|
+
.getObject({
|
|
51
64
|
objectId: upgradeCapId,
|
|
52
65
|
include: { json: true },
|
|
53
|
-
})
|
|
54
|
-
|
|
66
|
+
})
|
|
67
|
+
.then(({ object }) => object.json.package)
|
|
68
|
+
.finally(() => latestPackageIdCache.delete(upgradeCapId));
|
|
69
|
+
latestPackageIdCache.set(upgradeCapId, promise);
|
|
70
|
+
return promise;
|
|
71
|
+
}
|
|
72
|
+
// Keyed by owner + type + include mask, and scoped to the issuing client: two
|
|
73
|
+
// SuiGrpcClients can point at different endpoints or networks (this file builds
|
|
74
|
+
// beta-vs-mainnet constants off NEXT_PUBLIC_SUILEND_USE_BETA_MARKET, and a
|
|
75
|
+
// frontend swapping RPCs holds both clients briefly), so one client must never
|
|
76
|
+
// be served another's in-flight response.
|
|
77
|
+
//
|
|
78
|
+
// Same in-flight-only contract as latestPackageIdCache above: N lending markets
|
|
79
|
+
// asking for the same owner's caps at once collapse to one request, and the
|
|
80
|
+
// entry is dropped on settle so long-running processes never serve a stale
|
|
81
|
+
// object list.
|
|
82
|
+
const ownedObjectsCache = new WeakMap();
|
|
83
|
+
function ownedObjectsCacheFor(suiGrpcClient) {
|
|
84
|
+
const existing = ownedObjectsCache.get(suiGrpcClient);
|
|
85
|
+
if (existing)
|
|
86
|
+
return existing;
|
|
87
|
+
const created = new Map();
|
|
88
|
+
ownedObjectsCache.set(suiGrpcClient, created);
|
|
89
|
+
return created;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Lists every owned object of `type`, following pagination.
|
|
93
|
+
*
|
|
94
|
+
* `object_type` matches all instantiations when the type params are omitted
|
|
95
|
+
* (`0x2::coin::Coin` returns every `Coin<T>`), so passing a bare struct type
|
|
96
|
+
* lets one request serve callers that each only want their own type args.
|
|
97
|
+
* Filter the result on `obj.type` — comparing via normalizeStructTag, since
|
|
98
|
+
* the node returns fully-normalized addresses.
|
|
99
|
+
*/
|
|
100
|
+
export async function listAllOwnedObjects(suiGrpcClient, owner, type, include) {
|
|
101
|
+
// Encodes each flag's value, not just its presence, so {content: true} and
|
|
102
|
+
// {content: false} cannot collide on one key.
|
|
103
|
+
const key = `${owner}|${type}|${Object.entries(include ?? {})
|
|
104
|
+
.map(([flag, value]) => `${flag}=${value}`)
|
|
105
|
+
.sort()
|
|
106
|
+
.join(",")}`;
|
|
107
|
+
const cache = ownedObjectsCacheFor(suiGrpcClient);
|
|
108
|
+
const cached = cache.get(key);
|
|
109
|
+
if (cached)
|
|
110
|
+
return cached;
|
|
111
|
+
const promise = (async () => {
|
|
112
|
+
const allObjs = [];
|
|
113
|
+
let cursor = null;
|
|
114
|
+
let hasNextPage = true;
|
|
115
|
+
while (hasNextPage) {
|
|
116
|
+
const objs = await suiGrpcClient.listOwnedObjects({
|
|
117
|
+
owner,
|
|
118
|
+
cursor,
|
|
119
|
+
type,
|
|
120
|
+
include,
|
|
121
|
+
});
|
|
122
|
+
allObjs.push(...objs.objects);
|
|
123
|
+
cursor = objs.cursor;
|
|
124
|
+
hasNextPage = objs.hasNextPage;
|
|
125
|
+
}
|
|
126
|
+
return allObjs;
|
|
127
|
+
})().finally(() => cache.delete(key));
|
|
128
|
+
cache.set(key, promise);
|
|
129
|
+
return promise;
|
|
55
130
|
}
|
|
56
131
|
export class SuilendClient {
|
|
57
132
|
lendingMarket;
|
|
@@ -75,6 +150,53 @@ export class SuilendClient {
|
|
|
75
150
|
setPublishedAt(publishedAt);
|
|
76
151
|
return new SuilendClient(lendingMarket, suiGrpcClient);
|
|
77
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Same as `initialize`, but fetches every LendingMarket object in one
|
|
155
|
+
* request rather than one per market.
|
|
156
|
+
*/
|
|
157
|
+
static async initializeAll(lendingMarkets, suiGrpcClient, logPackageId) {
|
|
158
|
+
// Refreshed even for an empty list, so PUBLISHED_AT parity with
|
|
159
|
+
// initialize() holds for every call — move-call targets are built off that
|
|
160
|
+
// module global regardless of how many clients came back.
|
|
161
|
+
const publishedAt = await getLatestPackageId(suiGrpcClient, SUILEND_UPGRADE_CAP_ID);
|
|
162
|
+
if (logPackageId)
|
|
163
|
+
console.log("@suilend/sdk | publishedAt:", publishedAt);
|
|
164
|
+
setPublishedAt(publishedAt);
|
|
165
|
+
if (lendingMarkets.length === 0)
|
|
166
|
+
return [];
|
|
167
|
+
const { objects } = await suiGrpcClient.getObjects({
|
|
168
|
+
objectIds: lendingMarkets.map((lendingMarket) => lendingMarket.id),
|
|
169
|
+
include: { content: true },
|
|
170
|
+
});
|
|
171
|
+
// Paired by objectId rather than by position: BatchGetObjectsResponse
|
|
172
|
+
// documents no ordering guarantee, and every object here is a
|
|
173
|
+
// LendingMarket, so a type check cannot catch a reordered response — it
|
|
174
|
+
// would silently attach the wrong type arg to a market.
|
|
175
|
+
const objectById = new Map();
|
|
176
|
+
const failures = [];
|
|
177
|
+
for (const object of objects) {
|
|
178
|
+
// The error branch of GetObjectResult carries no objectId, so a failed
|
|
179
|
+
// entry cannot be attributed by id. Rather than fall back to position —
|
|
180
|
+
// which the pairing above deliberately does not trust — failures are
|
|
181
|
+
// identified by which requested ids are missing below.
|
|
182
|
+
if (object instanceof Error)
|
|
183
|
+
failures.push(object);
|
|
184
|
+
else
|
|
185
|
+
objectById.set(normalizeSuiObjectId(object.objectId), object);
|
|
186
|
+
}
|
|
187
|
+
return lendingMarkets.map(({ id, type }) => {
|
|
188
|
+
const object = objectById.get(normalizeSuiObjectId(id));
|
|
189
|
+
if (!object)
|
|
190
|
+
throw new Error(`Failed to fetch lending market ${id}${failures.length > 0 ? `: ${failures[0].message}` : ""}`, failures.length > 0 ? { cause: failures[0] } : undefined);
|
|
191
|
+
// Compares the full parameterized type, not just the struct name: an
|
|
192
|
+
// id/type pair built from two drifted lists would otherwise pass and
|
|
193
|
+
// decode under the wrong phantom type.
|
|
194
|
+
const expectedType = normalizeStructTag(`${PACKAGE_ID}::lending_market::LendingMarket<${type}>`);
|
|
195
|
+
if (normalizeStructTag(object.type) !== expectedType)
|
|
196
|
+
throw new Error(`object at id ${id} is not a LendingMarket<${type}> (got ${object.type})`);
|
|
197
|
+
return new SuilendClient(LendingMarket.fromBcs(phantom(type), object.content), suiGrpcClient);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
78
200
|
static async getFeeReceivers(suiGrpcClient, lendingMarketId) {
|
|
79
201
|
const { dynamicField } = await suiGrpcClient.getDynamicField({
|
|
80
202
|
parentId: lendingMarketId,
|
|
@@ -102,21 +224,11 @@ export class SuilendClient {
|
|
|
102
224
|
return ownerCap;
|
|
103
225
|
}
|
|
104
226
|
static async getObligationOwnerCaps(ownerId, lendingMarketTypeArgs, suiGrpcClient) {
|
|
105
|
-
const allObjs =
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
owner: ownerId,
|
|
111
|
-
cursor,
|
|
112
|
-
type: `${PACKAGE_ID}::lending_market::ObligationOwnerCap<${lendingMarketTypeArgs[0]}>`,
|
|
113
|
-
include: { content: true },
|
|
114
|
-
});
|
|
115
|
-
allObjs.push(...objs.objects);
|
|
116
|
-
cursor = objs.cursor;
|
|
117
|
-
hasNextPage = objs.hasNextPage;
|
|
118
|
-
}
|
|
119
|
-
return allObjs.map((obj) => ObligationOwnerCap.fromBcs(phantom(lendingMarketTypeArgs[0]), obj.content));
|
|
227
|
+
const allObjs = await listAllOwnedObjects(suiGrpcClient, ownerId, `${PACKAGE_ID}::lending_market::ObligationOwnerCap`, { content: true });
|
|
228
|
+
const type = normalizeStructTag(`${PACKAGE_ID}::lending_market::ObligationOwnerCap<${lendingMarketTypeArgs[0]}>`);
|
|
229
|
+
return allObjs
|
|
230
|
+
.filter((obj) => normalizeStructTag(obj.type) === type)
|
|
231
|
+
.map((obj) => ObligationOwnerCap.fromBcs(phantom(lendingMarketTypeArgs[0]), obj.content));
|
|
120
232
|
}
|
|
121
233
|
static async getObligation(obligationId, lendingMarketTypeArgs, suiGrpcClient) {
|
|
122
234
|
const { object } = await suiGrpcClient.getObject({
|
|
@@ -125,18 +237,27 @@ export class SuilendClient {
|
|
|
125
237
|
});
|
|
126
238
|
return Obligation.fromBcs(phantom(lendingMarketTypeArgs[0]), object.content);
|
|
127
239
|
}
|
|
240
|
+
// Batched analog of getObligation — chunkedMultiGet issues one getObjects
|
|
241
|
+
// call per 50 ids, run concurrently, instead of one getObject round-trip
|
|
242
|
+
// per id.
|
|
243
|
+
static async getObligations(obligationIds, lendingMarketTypeArgs, suiGrpcClient) {
|
|
244
|
+
if (obligationIds.length === 0)
|
|
245
|
+
return [];
|
|
246
|
+
const objects = await chunkedMultiGet(suiGrpcClient, obligationIds);
|
|
247
|
+
return objects.map((object) => {
|
|
248
|
+
if (object instanceof Error)
|
|
249
|
+
throw object;
|
|
250
|
+
return Obligation.fromBcs(phantom(lendingMarketTypeArgs[0]), object.content);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
128
253
|
async getObligation(obligationId) {
|
|
129
254
|
return SuilendClient.getObligation(obligationId, this.lendingMarket.$typeArgs, this.suiGrpcClient);
|
|
130
255
|
}
|
|
131
256
|
static async getLendingMarketOwnerCapId(ownerId, lendingMarketTypeArgs, suiGrpcClient) {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (objs.objects.length > 0)
|
|
137
|
-
return objs.objects[0].objectId;
|
|
138
|
-
else
|
|
139
|
-
return undefined;
|
|
257
|
+
const allObjs = await listAllOwnedObjects(suiGrpcClient, ownerId, `${PACKAGE_ID}::lending_market::LendingMarketOwnerCap`);
|
|
258
|
+
const type = normalizeStructTag(`${PACKAGE_ID}::lending_market::LendingMarketOwnerCap<${lendingMarketTypeArgs[0]}>`);
|
|
259
|
+
return allObjs.find((obj) => normalizeStructTag(obj.type) === type)
|
|
260
|
+
?.objectId;
|
|
140
261
|
}
|
|
141
262
|
async getLendingMarketOwnerCapId(ownerId) {
|
|
142
263
|
return SuilendClient.getLendingMarketOwnerCapId(ownerId, this.lendingMarket.$typeArgs, this.suiGrpcClient);
|
package/lib/initialize.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { normalizeStructTag } from "@mysten/sui/utils";
|
|
2
2
|
import BigNumber from "bignumber.js";
|
|
3
|
-
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,
|
|
4
|
-
import { LENDING_MARKET_ID, SuilendClient } from "../client.js";
|
|
3
|
+
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, getCoinMetadataMap, getPrice, isSendPoints, isSteammPoints, } from "@suilend/sui-core";
|
|
4
|
+
import { LENDING_MARKET_ID, SuilendClient, listAllOwnedObjects, } from "../client.js";
|
|
5
5
|
import { parseLendingMarket, parseObligation } from "../parsers/index.js";
|
|
6
6
|
import * as simulate from "../utils/simulate.js";
|
|
7
7
|
import { WAD } from "./constants.js";
|
|
@@ -302,7 +302,9 @@ export const initializeObligations = async (suiGrpcClient, suilendClient, refres
|
|
|
302
302
|
const hasStrategies = Object.values(STRATEGY_TYPE_INFO_MAP).some((info) => info.lendingMarketId === suilendClient.lendingMarket.id);
|
|
303
303
|
if (!hasStrategies)
|
|
304
304
|
return [];
|
|
305
|
-
const
|
|
305
|
+
const allObjects = await listAllOwnedObjects(suiGrpcClient, address, `${STRATEGY_WRAPPER_PACKAGE_ID_V1}::strategy_wrapper::StrategyOwnerCap`, { json: true });
|
|
306
|
+
const type = normalizeStructTag(`${STRATEGY_WRAPPER_PACKAGE_ID_V1}::strategy_wrapper::StrategyOwnerCap<${suilendClient.lendingMarket.$typeArgs[0]}>`);
|
|
307
|
+
const objects = allObjects.filter((obj) => normalizeStructTag(obj.type) === type);
|
|
306
308
|
return objects.map((obj) => {
|
|
307
309
|
const json = obj.json;
|
|
308
310
|
const id = json.id;
|
|
@@ -320,10 +322,10 @@ export const initializeObligations = async (suiGrpcClient, suilendClient, refres
|
|
|
320
322
|
})(),
|
|
321
323
|
SuilendClient.getObligationOwnerCaps(address, suilendClient.lendingMarket.$typeArgs, suiGrpcClient),
|
|
322
324
|
]);
|
|
323
|
-
const obligations = (await
|
|
325
|
+
const obligations = (await SuilendClient.getObligations([
|
|
324
326
|
...strategyOwnerCaps.map((soc) => soc.obligationId),
|
|
325
327
|
...obligationOwnerCaps.map((ownerCap) => ownerCap.obligationId),
|
|
326
|
-
]
|
|
328
|
+
], suilendClient.lendingMarket.$typeArgs, suiGrpcClient))
|
|
327
329
|
.map((rawObligation) => simulate.refreshObligation(rawObligation, refreshedRawReserves))
|
|
328
330
|
.map((refreshedObligation) => parseObligation(refreshedObligation, reserveMap, strategyOwnerCaps.some((soc) => soc.obligationId === refreshedObligation.id)))
|
|
329
331
|
.sort((a, b) => +b.netValueUsd.minus(a.netValueUsd));
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@suilend/sdk","version":"5.
|
|
1
|
+
{"name":"@suilend/sdk","version":"5.1.0","private":false,"description":"A TypeScript SDK for interacting with the Suilend program","author":"Suilend","license":"MIT","main":"./index.js","exports":{".":"./index.js","./mmt":"./mmt.js","./strategies":"./strategies.js","./client":"./client.js","./utils":"./utils/index.js","./utils/simulate":"./utils/simulate.js","./utils/obligation":"./utils/obligation.js","./utils/events":"./utils/events.js","./margin":"./margin/index.js","./lib/transactions":"./lib/transactions.js","./lib/strategyOwnerCap":"./lib/strategyOwnerCap.js","./lib/constants":"./lib/constants.js","./lib/types":"./lib/types.js","./lib":"./lib/index.js","./lib/pyth":"./lib/pyth.js","./lib/liquidityMining":"./lib/liquidityMining.js","./lib/initialize":"./lib/initialize.js","./lib/pythAdapter":"./lib/pythAdapter.js","./swap":"./swap/index.js","./swap/transaction":"./swap/transaction.js","./swap/quote":"./swap/quote.js","./parsers/reserve":"./parsers/reserve.js","./parsers/rateLimiter":"./parsers/rateLimiter.js","./parsers":"./parsers/index.js","./parsers/apiReserveAssetDataEvent":"./parsers/apiReserveAssetDataEvent.js","./parsers/obligation":"./parsers/obligation.js","./parsers/lendingMarket":"./parsers/lendingMarket.js","./api":"./api/index.js","./api/events":"./api/events.js","./margin/utils":"./margin/utils/index.js","./margin/margin/market":"./margin/margin/market.js","./margin/margin/version":"./margin/margin/version.js","./margin/margin/position":"./margin/margin/position.js","./margin/margin/router":"./margin/margin/router.js","./margin/margin/admin_cap":"./margin/margin/admin_cap.js","./margin/margin/permissions":"./margin/margin/permissions.js","./_generated/suilend":"./_generated/suilend/index.js","./_generated/_framework/reified":"./_generated/_framework/reified.js","./_generated/_framework/util":"./_generated/_framework/util.js","./_generated/_framework/vector":"./_generated/_framework/vector.js","./_generated/suilend/lending-market-registry/functions":"./_generated/suilend/lending-market-registry/functions.js","./_generated/suilend/obligation/structs":"./_generated/suilend/obligation/structs.js","./_generated/suilend/reserve-config/structs":"./_generated/suilend/reserve-config/structs.js","./_generated/suilend/reserve-config/functions":"./_generated/suilend/reserve-config/functions.js","./_generated/suilend/rate-limiter/structs":"./_generated/suilend/rate-limiter/structs.js","./_generated/suilend/rate-limiter/functions":"./_generated/suilend/rate-limiter/functions.js","./_generated/suilend/cell/structs":"./_generated/suilend/cell/structs.js","./_generated/suilend/liquidity-mining/structs":"./_generated/suilend/liquidity-mining/structs.js","./_generated/suilend/lending-market/structs":"./_generated/suilend/lending-market/structs.js","./_generated/suilend/lending-market/functions":"./_generated/suilend/lending-market/functions.js","./_generated/suilend/decimal/structs":"./_generated/suilend/decimal/structs.js","./_generated/suilend/reserve/structs":"./_generated/suilend/reserve/structs.js","./margin/margin/deps/suilend/lending_market":"./margin/margin/deps/suilend/lending_market.js","./margin/margin/deps/sui/vec_set":"./margin/margin/deps/sui/vec_set.js","./margin/margin/deps/std/type_name":"./margin/margin/deps/std/type_name.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","./_generated/_dependencies/source/0x1/option/structs":"./_generated/_dependencies/source/0x1/option/structs.js","./_generated/_dependencies/source/0x1/ascii/structs":"./_generated/_dependencies/source/0x1/ascii/structs.js","./_generated/_dependencies/source/0x1/type-name/structs":"./_generated/_dependencies/source/0x1/type-name/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/0x2/bag/structs":"./_generated/_dependencies/source/0x2/bag/structs.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-info/structs":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-info/structs.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price/structs":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price/structs.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-feed/structs":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-feed/structs.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/i64/structs":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/i64/structs.js"},"types":"./index.d.ts","scripts":{"build":"rm -rf ./dist && bun tsc && node ./fix-esm-imports.js","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.test.json","test":"bun test tests/","lint:ci":"bun run typecheck","prettier":"prettier --write src/ tests/","release":"bun run build && bun ./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.3.0","@cetusprotocol/aggregator-sdk":"^1.5.7","@flowx-finance/sdk":"^2.1.0","@pythnetwork/pyth-sui-js":"2.2.0","@suilend/springsui-sdk":"^4.0.0","bignumber.js":"^9.1.2","bn.js":"^5.2.2","crypto-js":"^4.2.0","lodash":"^4.17.21","p-limit":"3.1.0","uuid":"^11.0.3"},"devDependencies":{"@types/bn.js":"^5.2.0","@types/lodash":"^4.17.20","ts-node":"^10.9.2","typescript":"^6.0.3","@tsconfig/recommended":"^1.0.8","@types/node":"^22.9.0"},"peerDependencies":{"@mysten/bcs":"^2.0.5","@mysten/sui":"2.17.0","@suilend/sui-core":"^1.0.0"},"type":"module"}
|
package/utils/obligation.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { SuiClientTypes } from "@mysten/sui/client";
|
|
1
2
|
import { SuiGraphQLClient } from "@mysten/sui/graphql";
|
|
2
3
|
import { SuiGrpcClient } from "@mysten/sui/grpc";
|
|
3
4
|
import { Obligation } from "../_generated/suilend/obligation/structs";
|
|
4
5
|
import { ParsedObligation } from "../parsers";
|
|
5
6
|
export declare function fetchAllObligationsForMarketWithHandler(suiGrpcClient: SuiGrpcClient, lendingMarketId: string, lendingMarketType: string, chunkHandler: (obligations: Obligation<string>[]) => Promise<void>): Promise<void>;
|
|
6
7
|
export declare function fetchAllObligationsForMarket(suiGrpcClient: SuiGrpcClient, lendingMarketId: string, lendingMarketType: string): Promise<Obligation<string>[]>;
|
|
8
|
+
export declare function chunkedMultiGet(suiGrpcClient: SuiGrpcClient, objectIds: string[]): Promise<(Error | SuiClientTypes.Object<{
|
|
9
|
+
content: true;
|
|
10
|
+
}>)[]>;
|
|
7
11
|
export type FormattedObligationHistory = NonLiquidationHistoryEvent | LiquidationHistoryEvent;
|
|
8
12
|
export type NonLiquidationHistoryEvent = {
|
|
9
13
|
reserveId: string;
|
package/utils/obligation.js
CHANGED
|
@@ -66,7 +66,7 @@ export async function fetchAllObligationsForMarket(suiGrpcClient, lendingMarketI
|
|
|
66
66
|
}
|
|
67
67
|
return obligations;
|
|
68
68
|
}
|
|
69
|
-
async function chunkedMultiGet(suiGrpcClient, objectIds) {
|
|
69
|
+
export async function chunkedMultiGet(suiGrpcClient, objectIds) {
|
|
70
70
|
const limit = pLimit(30);
|
|
71
71
|
const results = [];
|
|
72
72
|
const chunks = splitIntoChunks(objectIds, 50);
|