npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

haedal-liquidity-layer-scripts

v2.0.6

Published

本文对应 `hearn/move/liquidity_layer/sdk`,面向前端/客户端调用。

Readme

Liquidity Layer Frontend SDK 使用说明

本文对应 hearn/move/liquidity_layer/sdk,面向前端/客户端调用。

  • 用户侧主类:LLVClient
  • 管理侧主类:LLVAdminClient

1. 初始化

import { LLVClient, LLVAdminClient } from "haedal-liquidity-layer-scripts";

const llvClient = new LLVClient(provider, {
  packageId: "0x<llv_core_pkg>",
  globalId: "0x<llv_global>",
  clockId: "0x6",
  shareTokenType: "0x<share_token_type>",

  // 方案C拆包时建议都传
  vaultPackageId: "0x<llv_ext_vault_pkg>",
  suilendPackageId: "0x<llv_ext_suilend_pkg>",
  scallopPackageId: "0x<llv_ext_scallop_pkg>",
  naviPackageId: "0x<llv_ext_navi_pkg>",
  cetusPackageId: "0x<llv_ext_cetus_pkg>",
  alphalendPackageId: "0x<llv_ext_alphalend_pkg>",
});

const adminClient = new LLVAdminClient({
  packageId: "0x<llv_core_pkg>",
  globalId: "0x<llv_global>",
  clockId: "0x6",
  shareTokenType: "0x<share_token_type>",
  globalAdminCapId: "0x<global_admin_cap>",

  naviPackageId: "0x<llv_ext_navi_pkg>",
  alphalendPackageId: "0x<llv_ext_alphalend_pkg>",
  vaultPackageId: "0x<llv_ext_vault_pkg>",
  suilendPackageId: "0x<llv_ext_suilend_pkg>",
  scallopPackageId: "0x<llv_ext_scallop_pkg>",
  cetusPackageId: "0x<llv_ext_cetus_pkg>",
});

2. 管理端配置池子(必须先完成)

clm-auth 下,推荐顺序:

  1. createAndSharePool
  2. configureProtocol
  3. initProtocolCap(仅 NAVI / AlphaLend
  4. addProtocol
  5. registerProtocolLegAuth(所有协议都需要)
  6. setSupplyQueue / setWithdrawQueue

2.1 一步法(推荐)

可直接使用:configureInitAddAndRegisterProtocol(...)

它会按顺序串联: configure_protocol -> init_*_cap(按需) -> add_protocol -> register_*_leg_auth

3. 仓位查询(新增,Phase 1)

合约新增了不会 abort 的查询函数,前端应优先使用。

3.0.1 一键获取提款展示信息(推荐)

// getWithdrawDisplayQuote: 聚合查询,返回前端展示所需的全部信息
const quote = await llvClient.getWithdrawDisplayQuote(sender, poolId, userShares);

// quote.positionValue      — 仓位总价值(会计值,含禁用协议)
// quote.actualWithdrawable — 当前实际可提取金额
// quote.recallPlan         — 参考分配计划(展示"从哪些协议提取")
// quote.isPartiallyLocked  — 是否部分锁定(positionValue > actualWithdrawable)

if (quote.isPartiallyLocked) {
  // 显示提示:"部分资金所在协议流动性受限"
}

3.0.2 查询仓位价值(会计值)

const positionValue = await llvClient.estimateSharesValue(sender, poolId, userShares);
// 返回 bigint: 纯 NAV 换算,忽略方向标志和流动性

3.0.3 查询可提取金额(操作值)

const result = await llvClient.previewWithdrawBySharesSafe(sender, poolId, userShares);
// result.navValue            — 仓位总价值(会计值)
// result.actualWithdrawable  — 当前实际可提取金额
// result.recallPlan          — 参考分配计划

3.0.4 按金额查询可提取信息

const result = await llvClient.previewWithdrawByAssetsSafe(sender, poolId, 800_000_000n);
// result.requestedShares     — 请求金额对应的 shares(ceil,会计值)
// result.maxSafeShares       — 可安全提交 begin_withdraw 的 shares 上限(floor)
// result.actualWithdrawable  — 当前实际可提取金额
// result.recallPlan          — 参考分配计划

3.0.5 查询用户最大可提取 shares(推荐用于 max 按钮)

// 用户级上限 = min(wallet + staked shares, 池级可提取上限)
// 传入 suiClient 以包含 farming staked shares
import { SuiClient } from "@mysten/sui/client";
const suiClient = new SuiClient({ url: "..." });
const userMax = await llvClient.getUserMaxWithdrawableShares(sender, poolId, { suiClient });

// 不传 suiClient 时,仅统计 wallet 内的 shares
// (farming staked shares 不计入;RPC 读取失败也静默降级为 wallet-only)
const walletOnlyMax = await llvClient.getUserMaxWithdrawableShares(sender, poolId);

如果只需要池级上限(不关心用户持仓):

// 池级上限(注意:不是用户级上限)
const poolMax = await llvClient.queryMaxWithdrawableShares(sender, poolId);

3.0.6 前端展示建议

总仓位价值:    110 SUI     ← quote.positionValue
当前可提取:     60 SUI     ← quote.actualWithdrawable

quote.isPartiallyLocked === true 时,显示提示:"部分资金所在协议流动性受限或方向控制已禁用"

3.0.7 新旧 SDK 方法对比

| SDK 方法 | 协议禁用时行为 | 适用场景 | |---------|--------------|---------| | previewWithdrawByShares()(旧) | throw | SDK 内部执行路径,不推荐前端直接调用 | | previewWithdrawBySharesSafe()(新) | 正常返回 | 前端查询展示 | | previewWithdrawByAssets()(旧) | throw | SDK 内部执行路径,不推荐前端直接调用 | | previewWithdrawByAssetsSafe()(新) | 正常返回 | 前端查询展示 | | estimateSharesValue()(新) | 正常返回 | 仓位价值展示 | | queryMaxWithdrawableShares()(新) | 正常返回 | 池级可提取上限(不含用户持仓信息) | | getUserMaxWithdrawableShares()(新) | 正常返回 | 用户级 max = min(wallet+staked, 池级上限);传入 suiClient 支持 farming | | getWithdrawDisplayQuote()(新) | 正常返回(shares=0 返回全 0) | 一键获取展示所需全部信息 |


3.1 存款(原有流程不变)

3.1 存款

const tx = await llvClient.deposit(
  poolId,
  sender,
  10n,                   // amount(按你传入 decimal 解释)
  assetType,             // 可不传,不传则从池子配置解析
  { slippageBps: 100n }, // 可选,默认 1%
  9,                     // decimal,可选;SUI 常用 9
);

await signAndExecuteTransaction({ transaction: tx });

SDK 内部会自动走:

  1. preview_deposit(devInspect)
  2. begin_deposit
  3. 按分配计划调用各协议 deposit_to_*
  4. complete_deposit

3.2 赎回

推荐流程:先查后取

// Step 1: 查询可提取信息(使用 safe 版本,不会 throw)
const quote = await llvClient.getWithdrawDisplayQuote(sender, poolId, userShares);

// Step 2: 前端展示
// “仓位价值: {quote.positionValue} SUI | 可提取: {quote.actualWithdrawable} SUI”
// if (quote.isPartiallyLocked) 显示流动性受限提示

// Step 3: 用户确认提取金额后,构造交易
const tx = await llvClient.withdraw(
  poolId,
  sender,
  sharesToWithdraw,      // 不超过 query_max_withdrawable_shares 的返回值
  0n,                    // minAssetsOut(可为 0,交给 slippage 自动推导)
  assetType,
  { slippageBps: 100n },
);

await signAndExecuteTransaction({ transaction: tx });

SDK 内部会自动走:

  1. 自动选择用户持有的 Coin<ShareToken>,能直接复用就不额外 merge/split
  2. final PTB dry-run quote
  3. begin_withdraw
  4. 按 recall plan 调用各协议 withdraw_from_*
  5. complete_withdraw_return(此处传入 min_assets_out 做最终安全检查)

如果前端是按”要拿多少资产”来发起赎回,推荐直接使用:

// 先查询:确认请求金额是否可执行
const preview = await llvClient.previewWithdrawByAssetsSafe(sender, poolId, assetsToWithdraw);

// 如果 preview.actualWithdrawable < assetsToWithdraw,提示用户:
// “请求提取 {assetsToWithdraw},但当前最多可提取 {preview.actualWithdrawable}”

// 用户确认后执行(使用实际可提取金额)
const tx = await llvClient.withdrawByAssets(
  poolId,
  sender,
  preview.actualWithdrawable,  // 使用实际可提取金额
  0n,                    // minAssetsOut(可为 0,交给 slippage 自动推导)
  assetType,
  { slippageBps: 100n },
);

await signAndExecuteTransaction({ transaction: tx });

withdrawByAssets 会先通过 preview_withdraw_by_assets 求出应烧毁的 shares,再沿用同一套 final quote 流程构造单次签名交易。

注意: withdraw / withdrawByAssets 内部仍使用旧的 preview_withdraw_by_shares(会 abort)。如果传入的 shares/assets 超过可提取上限,交易构造阶段就会失败。前端应先通过 _safe 版本查询,确保用户输入不超过 actual_withdrawable

4. 注意事项(高频坑位)

  1. register_*_leg_auth 之前,协议腿调用会因为 witness 鉴权失败而中止。
  2. NAVI / AlphaLend 未先执行 init_*_cap,会在 ext 调用阶段失败。
  3. 拆包部署必须传对各 ext package id,否则 moveCall target 会指向错误包。
  4. withdraw / withdrawByAssets 都会自动解析用户持有的 Coin<ShareToken>;如果已有单枚 coin 刚好够用,SDK 会直接复用它,避免额外对象抖动。
  5. 非 SUI 资产不要依赖 gas coin,SDK 会从用户资产币里 split;余额不足会直接报错。
  6. assetType 可不传,但前提是池子里 protocol_configs.type_bytes[1] 已正确配置。
  7. slippageBps 默认 100(1%),可按产品需求调大/调小。
  8. configure_protocolids/values 顺序必须严格匹配 Move 约束,否则会 abort。
  9. 禁用协议后查询仓位:当某协议 can_withdraw=false 时,旧的 preview_withdraw_by_shares 会 abort。前端必须使用 preview_withdraw_by_shares_safe 查询,它永远不会 abort。
  10. actual_withdrawable 是参考上限:查询时返回的 actual_withdrawable 基于链上记录的 current_balance 和方向标志,不含第三方协议的真实流动性(如 Suilend 借贷池利用率)。实际执行时,complete_withdraw_returnmin_assets_out 参数提供最终安全兜底。
  11. recall_plan 是参考值_safe 函数返回的 recall_plan 仅供前端展示"大约从哪些协议提取"。实际执行时 begin_withdraw 会重新计算 plan,可能因状态变化而略有不同。
  12. max_safe_shares 的语义preview_withdraw_by_assets_safe 返回的 max_safe_shares 是"可安全提交给 begin_withdraw 的 shares 上限"(floor 取整),不是"精确可执行的 shares"。执行时 begin_withdraw 会用该 shares 数重算 assets_to_receive,结果 ≤ actual_withdrawable

5. AlphaLend 特别说明

  • PROTOCOL_ALPHALEND = 5
  • 配置时:ids = [lending_protocol_id]values = [market_id]
  • 然后必须执行:init_alphalend_position_cap
  • 最后记得:add_protocol + register_alphalend_leg_auth