mcpField
T
tres-asset-balance-validation

tres-asset-balance-validation

github.com/anthropics数据与数据库4.8k51 次安装2 周前更新
代码仓库

关于 tres-asset-balance-validation

该技能将 Tres Finance 中的 EVM 钱包余额与 DeBank 数据进行核对,并生成交互式 HTML 和 PDF 差异报告。适用于需要验证资产余额、代币及 DeFi 仓位记录的 Tres Finance 用户。

主要功能

  1. 01核对 Tres Finance 与 DeBank 的代币余额
  2. 02比较 DeFi 仓位及其底层代币
  3. 03按链匹配资产并标记差异状态
  4. 04生成交互式 HTML 和 PDF 报告
  5. 05仅处理有余额的 EVM 钱包

适用场景

  1. 01审计 Tres Finance 追踪的 EVM 钱包余额
  2. 02检查链上数据与财务记录的差异
  3. 03核对 DeFi 仓位的底层代币数量

MCP 相关

该技能通过 TRES Finance 的 `get_viewer`、GraphQL 查询及 DeBank API 获取钱包和资产数据,随后比较结果并生成报告。README 未说明其向 MCP 客户端提供服务或工具。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/anthropics/claude-plugins-community --skill tres-asset-balance-validation

安装后在 Claude Code 中输入/tres-asset-balance-validation确认已加载。

详细介绍

Tres Finance — 资产余额验证

概述

此技能会将 Tres Finance 中的钱包余额与 DeBank 进行比对,并生成清晰的差异报告,同时提供交互式 HTML 文件和 PDF。它会比较每个 EVM 钱包中各项资产的代币数量(包括 DeFi 持仓的底层代币),并标记匹配、轻微差异、重大差异、缺失资产、未跟踪代币和未匹配持仓。

范围: 仅支持兼容 EVM 的钱包(DeBank 的限制)。交易所账户、非 EVM 链和空钱包会跳过。


适用场景

用户提出以下请求时,启用此技能:

  • 验证或核实其 TRES 余额
  • 根据外部链上数据交叉核对或审计钱包
  • 将 TRES 数据与 DeBank 进行比较
  • 检查其余额是否正确

示例短语:

  • “验证我的余额”
  • “对照 DeBank 检查我的钱包”
  • “我的 TRES 余额正确吗?”
  • “显示 TRES 与链上数据之间的差异”

前提条件

要求详情
TRES Finance 访问权限必须通过 get_viewer 完成身份验证
DeBank API 密钥可在 cloud.debank.com 免费获取
EVM 钱包TRES 中至少跟踪一个 0x... 钱包

流程概述

步骤 1 — 通过 TRES 验证身份

调用 get_viewer 确认组织名称。

步骤 2 — 从 TRES 获取钱包和余额

重要 — 超时处理: 对大型组织,同时包含 balances 和 positions 的 internalAccount 查询会超时。请拆分为两个独立查询:

查询 1:仅获取钱包和余额(不含持仓)

query {
  internalAccount {
    results {
      id
      name
      identifier
      isExchange
      platforms
      balances {
        amount
        asset {
          symbol
          contract { identifier }
        }
        fiatValue { value unitPrice fiatCurrency }
      }
    }
  }
}

注意: amount 字段以字符串而非数字形式返回。进行算术运算前务必先用 float() 转换。

钱包分类:

类型条件是否验证?
EVM0x... 地址 + EVM 平台 + isExchange: false✅ 是
交易所isExchange: true❌ 否
非 EVMBitcoin、Tezos、Tron 等❌ 否
空钱包没有资产余额❌ 否

支持的 EVM 平台: Ethereum、Arbitrum、Optimism、Polygon、Base、Avalanche、Binance、Gnosis Chain、zkSync、Fantom、Celo、Berachain、Linea、Scroll、Sonic、HyperEVM。

步骤 3 — 从 TRES 获取 DeFi 持仓

不要使用 internalAccount 的 positions 子字段——它会返回所有历史快照(每个钱包可能有 3000 多条记录),导致超时或超出令牌限制。

请改用专用的 getStatelessWalletsPositions 查询,该查询仅返回当前持仓:

query {
  getStatelessWalletsPositions(
    walletIdentifiers: ["0x..."],
    platform: ETHEREUM,
    application: "aave-v3"
  ) {
    walletIdentifier
    displayName
    positionType
    platform
    children {
      symbol
      amount
      assetIdentifier
      fiatValue
    }
    fiatValue
    id
  }
}

必需参数:

  • walletIdentifiers:钱包地址数组
  • platform:必须是枚举值,例如 ETHEREUM、POLYGON、ARBITRUM 等

可选但建议提供:

  • application:按协议筛选(例如 "aave-v3"、"verse"、"lido"、"merkl"、"uniswap-v4"、"sablier"、"ethena"、"stakewise"、"quickswap"、"steer"、"yieldnest"、"morphoblue")

重要: 不使用 application 筛选条件时,查询会返回空结果。务必指定应用。

分批策略:

  1. 首先,为每个钱包获取 DeBank all_complex_protocol_list,以确认哪些协议有持仓
  2. 将 DeBank 协议名称映射为 TRES 应用名称(小写并用连字符分隔)
  3. 使用 GraphQL 别名,将多个钱包、平台和应用的组合批量放入单个查询:
query {
  a1: getStatelessWalletsPositions(walletIdentifiers: ["0x..."], platform: ETHEREUM, application: "aave-v3") {
    walletIdentifier displayName positionType platform id
    children { symbol amount assetIdentifier fiatValue }
  }
  a2: getStatelessWalletsPositions(walletIdentifiers: ["0x..."], platform: ETHEREUM, application: "verse") {
    walletIdentifier displayName positionType platform id
    children { symbol amount assetIdentifier fiatValue }
  }
}

每个批量查询最多保留约 6 个别名,以避免超时。

步骤 4 — 获取 DeBank API 密钥

从插件用户配置中读取 DEBANK_API_KEY——不要要求用户在聊天中粘贴。 如果密钥缺失或为空,请停止并显示:

“未配置 DEBANK_API_KEY。请通过插件设置添加(请在 https://cloud.debank.com 获取密钥)。”

步骤 5 — 通过 bash 获取 DeBank 数据

对于每个 EVM 钱包,获取两个端点:

  1. 代币余额: all_token_list — 涵盖所有链,无需 chain_id
  2. DeFi 协议仓位: all_complex_protocol_list — 返回 LP、质押和借贷仓位及其底层代币数量

使用 -G 和 --data-urlencode,确保钱包地址不会通过 shell 插值到 URL 字符串中:

# Token balances
curl -s -G \
  -H "AccessKey: ${user_config.DEBANK_API_KEY}" \
  --data-urlencode "id=$WALLET_ADDR" \
  "https://pro-openapi.debank.com/v1/user/all_token_list"

# DeFi positions
curl -s -G \
  -H "AccessKey: ${user_config.DEBANK_API_KEY}" \
  --data-urlencode "id=$WALLET_ADDR" \
  "https://pro-openapi.debank.com/v1/user/all_complex_protocol_list"

**法币价值筛选:**丢弃所有 price < 0.01 的代币——这些代币不会参与任何匹配、显示或报告。

**速率限制:**钱包请求之间延迟 0.3s,以避免出现 429 错误。

步骤 6 — 匹配常规资产

匹配必须考虑链。DeBank 的 all_token_list 会为每个代币返回 chain 字段(例如 "eth"、"arb"、"bsc")。TRES 余额通过钱包的 platforms 数组或余额上下文与特定平台关联。应始终优先进行按链匹配,然后再回退到跨链汇总。

Chain ID 映射(DeBank chain → TRES 平台):

DeBank chainTRES 平台
ethETHEREUM
arbARBITRUM
opOPTIMISM
maticPOLYGON
baseBASE
bscBNB (Binance)
avaxAVALANCHE
ftmFANTOM
xdaiGNOSIS
eraZKSYNC
celoCELO
lineaLINEA
scrlSCROLL
mntMOONBEAM

匹配顺序(从最具体到最宽泛):

  1. **合约 + 链匹配(最佳):**将 asset.contract.identifier(小写)与 DeBank 代币的 id(小写)进行比较,并确保链相同。这是最精确的匹配方式。
  2. **符号 + 链匹配:**对于原生代币(没有合约),按 asset.symbol(不区分大小写)进行匹配,并确保 DeBank chain 与该余额行对应的 TRES 平台相符。这样可以正确处理常见情况:钱包在 Ethereum 和 Arbitrum 上都持有 ETH——每个 TRES 余额行都会匹配对应链上的 DeBank 条目。
  3. **仅按符号匹配(最后手段):**如果无法将 TRES 原生代币余额与任何特定的 DeBank 链条目匹配,则回退到仅按符号匹配。此方式可处理 TRES 或 DeBank 使用不同链标签的边缘情况。
步骤 7 — 匹配 DeFi 仓位的底层代币

这是一个关键步骤,用于比较 TRES 和 DeBank 中 DeFi 仓位的底层代币。

7a. 筛除仓位 NFT 行

从常规比较中移除仓位 NFT 代币(例如 UNI-V3-POS、RCL、SAB-LOCKUP、SLP、STEER、UNI-V4-POS)。这些代币会由仓位中的底层代币行取代。

7b. 处理 TRES 仓位

对于 getStatelessWalletsPositions 的结果,处理每个仓位:

  1. 按符号汇总 children——一个仓位可能包含同一代币的多个条目(例如 QuickSwap 或 Uniswap V4 中的供应量 + 未领取奖励),因此应将数量相加
  2. 使用 displayName 识别协议和代币组成
# Example: aggregate children for a position
def aggregate_children(children):
    agg = {}
    for c in children:
        sym = c['symbol']
        amt = float(c['amount']) if isinstance(c['amount'], str) else c['amount']
        if sym not in agg:
            agg[sym] = {'amount': 0, 'assetIdentifier': c.get('assetIdentifier', '')}
        agg[sym]['amount'] += amt
    return agg
7c. 处理 DeBank 仓位

对于 all_complex_protocol_list 中每个协议的 portfolio_item_list:

  1. 提取供应代币的 asset_token_list 和奖励的 reward_token_list
  2. 使用协议 name 和项目 name(例如 “Lending”“Liquidity Pool”)作为仓位标签
7d. 比较仓位代币

通过以下方式将 DeBank 协议仓位与 TRES 仓位匹配:

  1. 协议名称匹配(不区分大小写,取首个单词)
  2. 子项之间的代币符号重合

对于每个匹配的仓位代币:

  • **如果存在 TRES 数据:**比较数量,计算 delta %,并分配 match/minor/major 状态
  • **如果不存在 TRES 数据:**分配 position 状态(紫色徽标)
步骤 8 — 构建并渲染报告

创建两种输出:

  1. 交互式 HTML 文件 — 深色主题,包含筛选按钮、可折叠的钱包卡片,以及每个钱包专属的 DeFi Positions 部分
  2. PDF 报告 — 横向 A4,展开所有钱包表格,并使用 reportlab

将两者都保存到输出目录。


报告布局 — 至关重要

DeFi 持仓必须在视觉上区分开来

报告中的每张钱包卡片都 MUST 包含 两个独立的部分:

  1. DeFi 持仓部分(顶部,紫色主题)— 专属框,使用紫色边框和深紫色背景(背景色 #1a1033,边框色 #7c3aed),显示所有与持仓相关的行。此部分位于常规代币表格之前。

  2. 常规代币表格(下方)— 标准代币余额对比行。

持仓资产指示标记

每个持仓资产行都 MUST 在资产名称旁显示一个 紫色圆点指示标记(CSS 圆形,8px,#a855f7)。这样可以让人一眼识别出持仓:

<span style="display:inline-block;width:8px;height:8px;background:#a855f7;border-radius:50%;margin-right:6px;vertical-align:middle;"></span>

不要使用表情符号或内联 SVG — 它们可能无法在所有查看器中正确显示。仅使用纯 CSS 形状。

持仓行显示双徽标

与 TRES 匹配的持仓行会显示两个徽标:

  • POSITION 徽标(紫色)
  • 匹配状态徽标(MATCH/MINOR/MAJOR)
自动展开包含持仓的钱包

包含 DeFi 持仓的钱包卡片应自动展开(<details open>),以便立即查看持仓。


数字格式规则

代币数量
  • 所有数量最多保留 3 位小数
  • 数量 ≥ 1,000:使用逗号分隔,并保留 3 位小数(例如,846,492.356)
  • 数量 < 1,000:保留 3 位小数(例如,0.386)
  • 极小数量(< 0.000001):使用科学计数法(例如,3.54e-07)
  • 空值/缺失值:显示破折号 —
function formatAmount(n) {
  if (n === null || n === undefined) return '\u2014';
  if (Math.abs(n) < 0.000001) return n.toExponential(2);
  if (Math.abs(n) >= 1000) return n.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 3});
  return n.toFixed(3);
}
法币金额
  • 在每个代币数量旁以 括号 显示:846,492.356 ($17,562.21)
  • 在每个 delta % 旁以 括号 显示:5.33% ($81.21)
  • 格式:($X,XXX.XX) — 始终保留 2 位小数,并使用逗号分隔千位
  • 空值/缺失值:完全省略(不显示空括号)
法币金额计算 — 至关重要

使用单一价格来源(DeBank 的代币价格)计算 TRES 和 DeBank 两列的法币金额。这样可以确保:

  • 数量匹配时,法币差额为 $0(不会因价格来源不同而虚增)
  • delta % 旁的法币差额代表数量差异的实际美元价值
# For regular tokens:
price = debank_token['price']  # single source
tres_fiat = tres_amount * price
debank_fiat = debank_amount * price
delta_fiat = abs(tres_amount - debank_amount) * price

# For position tokens — same principle:
price = debank_asset_token['price']
tres_fiat = tres_aggregated_amount * price
debank_fiat = debank_amount * price
delta_fiat = abs(tres_aggregated_amount - debank_amount) * price

不要在 TRES 列使用 TRES 的 fiatValue,同时在 DeBank 列使用 DeBank 价格 — 当 TRES 和 DeBank 使用不同的代币价格时,这会造成误导性的法币差额。


原生代币匹配(多链钱包)

对于单个钱包,原生代币(ETH、BNB 等)通常会在 TRES 中出现在多条链上(例如,以太坊上的 ETH + Arbitrum 上的 ETH)。DeBank 的 all_token_list 会返回按链分别列出的条目,其中包含 chain 字段 — 它不会进行汇总。

规则:优先按链匹配,仅在最后手段时才汇总。

  1. 按链匹配(默认): 对于每个 TRES 原生代币余额,使用该余额的平台上下文,通过代币符号 + 链查找对应的 DeBank 条目。例如,某钱包在以太坊上有 0.00956 ETH、在 Arbitrum 上有 0.001168 ETH,应生成两个独立的对比行 — 一个匹配 DeBank 的 chain: "eth" 条目,另一个匹配 chain: "arb"。

  2. 汇总回退方案(少见): 仅当对于同一代币符号,DeBank 返回的条目数少于 TRES 时,才汇总不同链上的 TRES 余额。如果 DeBank 合并了某些跨链代币余额,就可能出现这种情况。汇总时,应添加类似 "Aggregated: ETH (eth) + ETH (arb)" 的备注。

为何重要: 比较前盲目汇总会造成错误差异。如果以太坊上的 ETH 完全匹配,但 Arbitrum 上的 ETH 存在差额,汇总就会掩盖以太坊上的匹配,并产生单个误导性差额。按链匹配可保留细分信息,便于准确找出不同步的链。


状态徽章

徽章颜色十六进制含义
匹配绿色#22c55e差异 < 1%
轻微橙色#f59e0b差异 1–10%
严重红色#ef4444差异 > 10%
缺失灰色#6b7280TRES 中存在此资产,但在 DeBank 中未找到
未跟踪蓝色#3b82f6DeBank 中存在此资产,但 TRES 未跟踪
仓位紫色#a855f7DeFi 仓位代币(有或没有 TRES 数据)

报告章节

渲染后的报告(HTML 和 PDF)包括:

  1. 摘要卡片 — 已检查的钱包数、已比较的资产数、匹配、轻微、严重、缺失、未跟踪、仓位,以及匹配率 %
  2. 筛选栏(仅 HTML)— 按状态筛选的按钮:全部、匹配、轻微、严重、缺失、未跟踪、仓位
  3. 每个钱包的卡片,包含:
    • DeFi 仓位框(顶部,紫色主题)— 仓位资产带有紫色圆点指示器、协议标签和双状态徽章
    • 常规代币表格 — 每项资产包含符号、链、TRES 数量(+ 法币金额)、DeBank 数量(+ 法币金额)、差异 %(+ 法币差额)和状态徽章
  4. 已跳过的钱包 — 未验证的钱包列表及跳过原因
  5. 备注与注意事项 — 同步延迟、DeFi 仓位说明、原生代币汇总、价格筛选,以及缺失/未跟踪项说明

重要注意事项

  • 同步延迟: TRES 余额反映最近一次同步时间。近期链上活动可能会显示为差异。
  • DeFi 仓位: LP、质押和借贷仓位中的底层代币会在专门的紫色区域中按行显示。若有 TRES 仓位数据,则会比较 TRES 和 DeBank 的数量。由于 TRES 和 DeBank 的快照时间不同,活跃 LP 仓位自然会显示出一些差异。
  • 原生代币匹配: ETH、BNB 等会先按链匹配(将 DeBank 的 chain 字段映射到 TRES 平台)。只有当 DeBank 返回的同符号条目少于 TRES 时,才会将多链余额汇总作为后备方案。
  • 多链覆盖范围: DeBank 的 all_token_list 涵盖所有链;TRES 中未配置的链上的代币会显示为“未跟踪”。
  • 价格筛选: 所有报告都会排除 price < $0.01 的代币(价格为零、为空或属于微型市值代币)。
  • DeBank 中缺失: 通常是 DeBank 过滤掉的垃圾/空投代币(HEX、ASCZBR 等)。
  • TRES 中未跟踪: 位于 TRES 未配置链上的代币,或数量很少的零散余额。

错误处理

情况响应
DeBank 401 错误在产物中显示“API 密钥无效”
DeBank 429 错误显示“请求过于频繁 — 60 秒后重新加载”
非空钱包的代币列表为空将钱包标记为可疑
非 EVM 钱包跳过,并列入“已跳过的钱包”部分
internalAccount 仓位请求超时改为按每个钱包/平台/应用使用 getStatelessWalletsPositions
getStatelessWalletsPositions 返回空结果确保提供了 application 参数;不提供该参数时,查询会返回空结果
无法提取仓位 ID跳过该仓位(不要导致程序崩溃)
amount 字段是字符串而非数字算术运算前始终使用 float() 进行转换

后续步骤(报告渲染完成后)

  • 重新运行 — 随时使用最新数据重新生成报告
  • 深入调查 — 对于任何严重差异,在 TRES 中检查各平台上的具体资产,以确定哪个链未同步
  • 仓位差异 — 由于 TRES 和 DeBank 的快照时间不同,活跃 LP 仓位出现轻微差异是预期情况

评论

支持 Markdown