@suilend/sdk 12.5.0 → 12.6.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.
Files changed (2) hide show
  1. package/client.js +87 -14
  2. package/package.json +1 -1
package/client.js CHANGED
@@ -50,6 +50,17 @@ export const ADMIN_ADDRESS = process.env.NEXT_PUBLIC_SUILEND_USE_BETA_MARKET ===
50
50
  const SUILEND_UPGRADE_CAP_ID = process.env.NEXT_PUBLIC_SUILEND_USE_BETA_MARKET === "true"
51
51
  ? "0x05da14368a42a351e106806c09727968ae26be77a6741a018239ef0f99d5185e"
52
52
  : "0x3d4ef1859c3ee9fc72858f588b56a09da5466e64f8cc4e90a7b3b909fba8a7ae";
53
+ // A suilend package accepts only markets whose `version` equals the
54
+ // CURRENT_VERSION it was compiled with, and the UpgradeCap names the newest
55
+ // package before any market migrates to it. So only the newest market version
56
+ // follows the cap; each older version pins the last package built for it.
57
+ const LATEST_MARKET_VERSION = BigInt(8);
58
+ const PUBLISHED_AT_BY_MARKET_VERSION = new Map([
59
+ [
60
+ BigInt(7),
61
+ "0x59672975e15c58ffc9450f5236b6aa9fa2407d94b8081e634778aa01957d8c6f",
62
+ ],
63
+ ]);
53
64
  export const LENDING_MARKET_REGISTRY_ID = process.env.NEXT_PUBLIC_SUILEND_USE_BETA_MARKET === "true"
54
65
  ? "0x925c9a2336b02fc2b68099837bd66f6b5b4d45cd460e0a4b81708bac6c440eff"
55
66
  : "0x64faff8d91a56c4f55debbb44767b009ee744a70bc2cc8e3bbd2718c92f85931";
@@ -242,6 +253,54 @@ function applyPublishedAt(publishedAt, logPackageId) {
242
253
  console.log("@suilend/sdk | publishedAt:", publishedAt);
243
254
  setPublishedAt(publishedAt);
244
255
  }
256
+ function startLatestPackageIdRead(suiGrpcClient) {
257
+ const latestPackageId = getLatestPackageId(suiGrpcClient, SUILEND_UPGRADE_CAP_ID);
258
+ // Read eagerly to overlap the market fetch, but unused while MAIN's version
259
+ // is pinned: an unobserved rejection would crash a bun process.
260
+ latestPackageId.catch(() => { });
261
+ return latestPackageId;
262
+ }
263
+ async function publishedAtForMainVersion(mainVersion, latestPackageId) {
264
+ if (process.env.NEXT_PUBLIC_SUILEND_USE_BETA_MARKET === "true" ||
265
+ mainVersion === LATEST_MARKET_VERSION)
266
+ return latestPackageId;
267
+ const pinned = PUBLISHED_AT_BY_MARKET_VERSION.get(mainVersion);
268
+ if (!pinned)
269
+ throw new Error(`No suilend package is known for lending market version ${mainVersion} (MAIN ${LENDING_MARKET_ID})`);
270
+ return pinned;
271
+ }
272
+ async function readMainVersion(suiGrpcClient) {
273
+ const { object } = await suiGrpcClient.getObject({
274
+ objectId: LENDING_MARKET_ID,
275
+ include: { content: true },
276
+ });
277
+ const expectedType = `${PACKAGE_ID}::lending_market::LendingMarket<${LENDING_MARKET_TYPE}>`;
278
+ if (!object.type ||
279
+ normalizeStructTag(object.type) !== normalizeStructTag(expectedType))
280
+ throw new Error(`object at id ${LENDING_MARKET_ID} is not a ${expectedType} (got ${object.type})`);
281
+ // LendingMarket's BCS starts with its 32-byte UID, then `version: u64`, so
282
+ // the version is read without decoding every reserve.
283
+ return BigInt(bcs.u64().parse(object.content.subarray(32, 40)));
284
+ }
285
+ // Same in-flight-only contract as ownedObjectsCache: N markets initializing at
286
+ // once share one MAIN read, and nothing outlives settlement, so a long-running
287
+ // process sees a migrate on its next initialize.
288
+ const mainVersionInFlight = new WeakMap();
289
+ function fetchMainVersion(suiGrpcClient) {
290
+ const inFlight = mainVersionInFlight.get(suiGrpcClient);
291
+ if (inFlight)
292
+ return inFlight;
293
+ const promise = readMainVersion(suiGrpcClient).finally(() => mainVersionInFlight.delete(suiGrpcClient));
294
+ mainVersionInFlight.set(suiGrpcClient, promise);
295
+ return promise;
296
+ }
297
+ function isMainMarket(lendingMarketId) {
298
+ return (normalizeSuiObjectId(lendingMarketId) ===
299
+ normalizeSuiObjectId(LENDING_MARKET_ID));
300
+ }
301
+ function versionMismatch(lendingMarketId, version, mainVersion) {
302
+ return `lending market ${lendingMarketId} is at version ${version}, but MAIN ${LENDING_MARKET_ID} is at version ${mainVersion}, so the suilend package chosen for MAIN aborts on its writes`;
303
+ }
245
304
  function clientsFromObjects(lendingMarkets, objects, suiGrpcClient) {
246
305
  // Paired by objectId rather than by position: BatchGetObjectsResponse
247
306
  // documents no ordering guarantee, and every object here is a
@@ -316,9 +375,17 @@ export class SuilendClient {
316
375
  this.pythConnection = resolvePriceUpdateDataSource();
317
376
  }
318
377
  static async initialize(lendingMarketId, lendingMarketType, suiGrpcClient, logPackageId) {
319
- const lendingMarket = await LendingMarket.fetch(suiGrpcClient, phantom(lendingMarketType), lendingMarketId);
320
- const publishedAt = await getLatestPackageId(suiGrpcClient, SUILEND_UPGRADE_CAP_ID);
321
- applyPublishedAt(publishedAt, logPackageId);
378
+ const latestPackageId = startLatestPackageIdRead(suiGrpcClient);
379
+ const [lendingMarket, fetchedMainVersion] = await Promise.all([
380
+ LendingMarket.fetch(suiGrpcClient, phantom(lendingMarketType), lendingMarketId),
381
+ isMainMarket(lendingMarketId)
382
+ ? undefined
383
+ : fetchMainVersion(suiGrpcClient),
384
+ ]);
385
+ const mainVersion = fetchedMainVersion ?? lendingMarket.version;
386
+ if (lendingMarket.version !== mainVersion)
387
+ throw new Error(versionMismatch(lendingMarketId, lendingMarket.version, mainVersion));
388
+ applyPublishedAt(await publishedAtForMainVersion(mainVersion, latestPackageId), logPackageId);
322
389
  return new SuilendClient(lendingMarket, suiGrpcClient);
323
390
  }
324
391
  /**
@@ -326,25 +393,31 @@ export class SuilendClient {
326
393
  * request rather than one per market.
327
394
  */
328
395
  static async initializeAll(lendingMarkets, suiGrpcClient, logPackageId) {
329
- // Refreshed even for an empty list, so PUBLISHED_AT parity with
330
- // initialize() holds for every call — move-call targets are built off that
331
- // module global regardless of how many clients came back.
332
- const [packageId, objects] = await Promise.allSettled([
333
- getLatestPackageId(suiGrpcClient, SUILEND_UPGRADE_CAP_ID).then((publishedAt) => applyPublishedAt(publishedAt, logPackageId)),
396
+ // Chosen even for an empty list: move-call targets are built off the
397
+ // PUBLISHED_AT module global regardless of how many clients came back. Like
398
+ // initialize(), a call that fails at any read leaves it unchanged.
399
+ const latestPackageId = startLatestPackageIdRead(suiGrpcClient);
400
+ const mainRequested = lendingMarkets.some(({ id }) => isMainMarket(id));
401
+ const [objects, fetchedMainVersion] = await Promise.all([
334
402
  lendingMarkets.length === 0
335
403
  ? []
336
404
  : suiGrpcClient
337
405
  .getObjects({
338
- objectIds: lendingMarkets.map((lendingMarket) => lendingMarket.id),
406
+ objectIds: lendingMarkets.map(({ id }) => id),
339
407
  include: { content: true },
340
408
  })
341
409
  .then((response) => response.objects),
410
+ mainRequested ? undefined : fetchMainVersion(suiGrpcClient),
342
411
  ]);
343
- if (packageId.status === "rejected")
344
- throw packageId.reason;
345
- if (objects.status === "rejected")
346
- throw objects.reason;
347
- return clientsFromObjects(lendingMarkets, objects.value, suiGrpcClient);
412
+ const clients = clientsFromObjects(lendingMarkets, objects, suiGrpcClient);
413
+ const mainVersion = fetchedMainVersion ??
414
+ clients[lendingMarkets.findIndex(({ id }) => isMainMarket(id))]
415
+ .lendingMarket.version;
416
+ applyPublishedAt(await publishedAtForMainVersion(mainVersion, latestPackageId), logPackageId);
417
+ for (const { lendingMarket } of clients)
418
+ if (lendingMarket.version !== mainVersion)
419
+ console.warn(`@suilend/sdk | ${versionMismatch(lendingMarket.id, lendingMarket.version, mainVersion)}`);
420
+ return clients;
348
421
  }
349
422
  static initializeAllFromObjects(lendingMarkets, objects, publishedAt, suiGrpcClient, logPackageId) {
350
423
  if (!isValidSuiAddress(publishedAt))
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@suilend/sdk","version":"12.5.0","private":false,"description":"A TypeScript SDK for interacting with the Suilend program","author":"Suilend","license":"MIT","main":"./index.js","exports":{".":"./index.js","./client":"./client.js","./mmt":"./mmt.js","./strategies":"./strategies.js","./api/events":"./api/events.js","./api":"./api/index.js","./lib/constants":"./lib/constants.js","./lib":"./lib/index.js","./lib/initialize":"./lib/initialize.js","./lib/liquidityMining":"./lib/liquidityMining.js","./lib/proCompatible":"./lib/proCompatible.js","./lib/pyth":"./lib/pyth.js","./lib/strategyOwnerCap":"./lib/strategyOwnerCap.js","./lib/transactions":"./lib/transactions.js","./lib/types":"./lib/types.js","./margin":"./margin/index.js","./parsers/apiReserveAssetDataEvent":"./parsers/apiReserveAssetDataEvent.js","./parsers":"./parsers/index.js","./parsers/lendingMarket":"./parsers/lendingMarket.js","./parsers/obligation":"./parsers/obligation.js","./parsers/rateLimiter":"./parsers/rateLimiter.js","./parsers/reserve":"./parsers/reserve.js","./swap":"./swap/index.js","./swap/quote":"./swap/quote.js","./swap/transaction":"./swap/transaction.js","./utils/events":"./utils/events.js","./utils/feedId":"./utils/feedId.js","./utils":"./utils/index.js","./utils/obligation":"./utils/obligation.js","./utils/simulate":"./utils/simulate.js","./_generated/_framework/reified":"./_generated/_framework/reified.js","./_generated/_framework/util":"./_generated/_framework/util.js","./_generated/_framework/vector":"./_generated/_framework/vector.js","./_generated/suilend":"./_generated/suilend/index.js","./margin/margin/admin_cap":"./margin/margin/admin_cap.js","./margin/margin/market":"./margin/margin/market.js","./margin/margin/permissions":"./margin/margin/permissions.js","./margin/margin/position":"./margin/margin/position.js","./margin/margin/router":"./margin/margin/router.js","./margin/margin/version":"./margin/margin/version.js","./margin/utils":"./margin/utils/index.js","./_generated/suilend/cell/structs":"./_generated/suilend/cell/structs.js","./_generated/suilend/decimal/structs":"./_generated/suilend/decimal/structs.js","./_generated/suilend/lending-market/functions":"./_generated/suilend/lending-market/functions.js","./_generated/suilend/lending-market/structs":"./_generated/suilend/lending-market/structs.js","./_generated/suilend/lending-market-registry/functions":"./_generated/suilend/lending-market-registry/functions.js","./_generated/suilend/liquidity-mining/structs":"./_generated/suilend/liquidity-mining/structs.js","./_generated/suilend/obligation/structs":"./_generated/suilend/obligation/structs.js","./_generated/suilend/rate-limiter/functions":"./_generated/suilend/rate-limiter/functions.js","./_generated/suilend/rate-limiter/structs":"./_generated/suilend/rate-limiter/structs.js","./_generated/suilend/reserve/structs":"./_generated/suilend/reserve/structs.js","./_generated/suilend/reserve-config/functions":"./_generated/suilend/reserve-config/functions.js","./_generated/suilend/reserve-config/structs":"./_generated/suilend/reserve-config/structs.js","./_generated/_dependencies/source/0x1":"./_generated/_dependencies/source/0x1/index.js","./_generated/_dependencies/source/0x2":"./_generated/_dependencies/source/0x2/index.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/index.js","./margin/margin/deps/std/type_name":"./margin/margin/deps/std/type_name.js","./margin/margin/deps/sui/vec_set":"./margin/margin/deps/sui/vec_set.js","./margin/margin/deps/suilend/lending_market":"./margin/margin/deps/suilend/lending_market.js","./_generated/_dependencies/source/0x1/ascii/structs":"./_generated/_dependencies/source/0x1/ascii/structs.js","./_generated/_dependencies/source/0x1/option/structs":"./_generated/_dependencies/source/0x1/option/structs.js","./_generated/_dependencies/source/0x1/type-name/structs":"./_generated/_dependencies/source/0x1/type-name/structs.js","./_generated/_dependencies/source/0x2/bag/structs":"./_generated/_dependencies/source/0x2/bag/structs.js","./_generated/_dependencies/source/0x2/balance/structs":"./_generated/_dependencies/source/0x2/balance/structs.js","./_generated/_dependencies/source/0x2/object/structs":"./_generated/_dependencies/source/0x2/object/structs.js","./_generated/_dependencies/source/0x2/object-table/structs":"./_generated/_dependencies/source/0x2/object-table/structs.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs.js"},"types":"./index.d.ts","scripts":{"build":"rm -rf ./dist && tsc && node ./fix-esm-imports.js","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.test.json","test":"vitest run","lint:ci":"yarn run typecheck","prettier":"prettier --write src/ tests/","release":"yarn run build && node ./release.js && cd ./dist && npm publish --access public"},"repository":{"type":"git","url":"git+https://github.com/fireflyprotocol/lending-mono.git","directory":"ts/sdks/sdk"},"dependencies":{"@bluefin-exchange/bluefin7k-aggregator-sdk":"7.6.3","@cetusprotocol/aggregator-sdk":"1.7.3","@flowx-finance/sdk":"2.1.0","@pythnetwork/hermes-client":"3.1.0","@pythnetwork/pyth-sui-js":"4.0.0","@suilend/springsui-sdk":"4.1.0","bignumber.js":"11.1.5","bn.js":"5.2.5","crypto-js":"4.2.0","lodash":"4.18.1","p-limit":"7.3.3","uuid":"14.0.2"},"devDependencies":{"@mysten/bcs":"2.1.1","@mysten/sui":"2.29.0","@suilend/sui-core":"2.1.0","@tsconfig/recommended":"1.0.13","@types/bn.js":"5.2.0","@types/lodash":"4.17.25","@types/node":"26.5.1","fast-check":"4.10.2","prettier":"3.9.9","ts-node":"10.9.2","typescript":"6.0.3","vite":"8.3.0","vitest":"5.0.1"},"peerDependencies":{"@mysten/bcs":"^2.1.1","@mysten/sui":">=2.22.1 <3","@suilend/sui-core":"^2.0.1"},"type":"module"}
1
+ {"name":"@suilend/sdk","version":"12.6.0","private":false,"description":"A TypeScript SDK for interacting with the Suilend program","author":"Suilend","license":"MIT","main":"./index.js","exports":{".":"./index.js","./client":"./client.js","./mmt":"./mmt.js","./strategies":"./strategies.js","./api/events":"./api/events.js","./api":"./api/index.js","./lib/constants":"./lib/constants.js","./lib":"./lib/index.js","./lib/initialize":"./lib/initialize.js","./lib/liquidityMining":"./lib/liquidityMining.js","./lib/proCompatible":"./lib/proCompatible.js","./lib/pyth":"./lib/pyth.js","./lib/strategyOwnerCap":"./lib/strategyOwnerCap.js","./lib/transactions":"./lib/transactions.js","./lib/types":"./lib/types.js","./margin":"./margin/index.js","./parsers/apiReserveAssetDataEvent":"./parsers/apiReserveAssetDataEvent.js","./parsers":"./parsers/index.js","./parsers/lendingMarket":"./parsers/lendingMarket.js","./parsers/obligation":"./parsers/obligation.js","./parsers/rateLimiter":"./parsers/rateLimiter.js","./parsers/reserve":"./parsers/reserve.js","./swap":"./swap/index.js","./swap/quote":"./swap/quote.js","./swap/transaction":"./swap/transaction.js","./utils/events":"./utils/events.js","./utils/feedId":"./utils/feedId.js","./utils":"./utils/index.js","./utils/obligation":"./utils/obligation.js","./utils/simulate":"./utils/simulate.js","./_generated/_framework/reified":"./_generated/_framework/reified.js","./_generated/_framework/util":"./_generated/_framework/util.js","./_generated/_framework/vector":"./_generated/_framework/vector.js","./_generated/suilend":"./_generated/suilend/index.js","./margin/margin/admin_cap":"./margin/margin/admin_cap.js","./margin/margin/market":"./margin/margin/market.js","./margin/margin/permissions":"./margin/margin/permissions.js","./margin/margin/position":"./margin/margin/position.js","./margin/margin/router":"./margin/margin/router.js","./margin/margin/version":"./margin/margin/version.js","./margin/utils":"./margin/utils/index.js","./_generated/suilend/cell/structs":"./_generated/suilend/cell/structs.js","./_generated/suilend/decimal/structs":"./_generated/suilend/decimal/structs.js","./_generated/suilend/lending-market/functions":"./_generated/suilend/lending-market/functions.js","./_generated/suilend/lending-market/structs":"./_generated/suilend/lending-market/structs.js","./_generated/suilend/lending-market-registry/functions":"./_generated/suilend/lending-market-registry/functions.js","./_generated/suilend/liquidity-mining/structs":"./_generated/suilend/liquidity-mining/structs.js","./_generated/suilend/obligation/structs":"./_generated/suilend/obligation/structs.js","./_generated/suilend/rate-limiter/functions":"./_generated/suilend/rate-limiter/functions.js","./_generated/suilend/rate-limiter/structs":"./_generated/suilend/rate-limiter/structs.js","./_generated/suilend/reserve/structs":"./_generated/suilend/reserve/structs.js","./_generated/suilend/reserve-config/functions":"./_generated/suilend/reserve-config/functions.js","./_generated/suilend/reserve-config/structs":"./_generated/suilend/reserve-config/structs.js","./_generated/_dependencies/source/0x1":"./_generated/_dependencies/source/0x1/index.js","./_generated/_dependencies/source/0x2":"./_generated/_dependencies/source/0x2/index.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/index.js","./margin/margin/deps/std/type_name":"./margin/margin/deps/std/type_name.js","./margin/margin/deps/sui/vec_set":"./margin/margin/deps/sui/vec_set.js","./margin/margin/deps/suilend/lending_market":"./margin/margin/deps/suilend/lending_market.js","./_generated/_dependencies/source/0x1/ascii/structs":"./_generated/_dependencies/source/0x1/ascii/structs.js","./_generated/_dependencies/source/0x1/option/structs":"./_generated/_dependencies/source/0x1/option/structs.js","./_generated/_dependencies/source/0x1/type-name/structs":"./_generated/_dependencies/source/0x1/type-name/structs.js","./_generated/_dependencies/source/0x2/bag/structs":"./_generated/_dependencies/source/0x2/bag/structs.js","./_generated/_dependencies/source/0x2/balance/structs":"./_generated/_dependencies/source/0x2/balance/structs.js","./_generated/_dependencies/source/0x2/object/structs":"./_generated/_dependencies/source/0x2/object/structs.js","./_generated/_dependencies/source/0x2/object-table/structs":"./_generated/_dependencies/source/0x2/object-table/structs.js","./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs":"./_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs.js"},"types":"./index.d.ts","scripts":{"build":"rm -rf ./dist && tsc && node ./fix-esm-imports.js","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.test.json","test":"vitest run","lint:ci":"yarn run typecheck","prettier":"prettier --write src/ tests/","release":"yarn run build && node ./release.js && cd ./dist && npm publish --access public"},"repository":{"type":"git","url":"git+https://github.com/fireflyprotocol/lending-mono.git","directory":"ts/sdks/sdk"},"dependencies":{"@bluefin-exchange/bluefin7k-aggregator-sdk":"7.6.3","@cetusprotocol/aggregator-sdk":"1.7.3","@flowx-finance/sdk":"2.1.0","@pythnetwork/hermes-client":"3.1.0","@pythnetwork/pyth-sui-js":"4.0.0","@suilend/springsui-sdk":"4.1.0","bignumber.js":"11.1.5","bn.js":"5.2.5","crypto-js":"4.2.0","lodash":"4.18.1","p-limit":"7.3.3","uuid":"14.0.2"},"devDependencies":{"@mysten/bcs":"2.1.1","@mysten/sui":"2.29.0","@suilend/sui-core":"2.1.0","@tsconfig/recommended":"1.0.13","@types/bn.js":"5.2.0","@types/lodash":"4.17.25","@types/node":"26.5.1","fast-check":"4.10.2","prettier":"3.9.9","ts-node":"10.9.2","typescript":"6.0.3","vite":"8.3.0","vitest":"5.0.1"},"peerDependencies":{"@mysten/bcs":"^2.1.1","@mysten/sui":">=2.22.1 <3","@suilend/sui-core":"^2.0.1"},"type":"module"}