Skip to main content
ClaudeWave
Skill3.3k repo starsupdated 11d ago

tres-asset-balance-validation

>

Install in Claude Code
Copy
git clone --depth 1 https://github.com/anthropics/claude-plugins-community /tmp/tres-asset-balance-validation && cp -r /tmp/tres-asset-balance-validation/tres-finance-plugin/skills/tres-asset-balance-validation ~/.claude/skills/tres-asset-balance-validation
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Tres Finance — Asset Balance Validation

## Overview

This skill validates wallet balances in **Tres Finance** against **DeBank**, providing a clear discrepancy report as both an interactive HTML file and a PDF. It compares per-asset token amounts (including DeFi position underlying tokens) for each EVM wallet and flags matches, minor differences, major discrepancies, missing assets, untracked tokens, and unmatched positions.

> **Scope:** Only EVM-compatible wallets are supported (DeBank limitation). Exchange accounts, non-EVM chains, and empty wallets are skipped.

---

## When to Use

Trigger this skill whenever a user asks to:

- Validate or verify their TRES balances
- Cross-check or audit wallets against external on-chain data
- Compare TRES data to DeBank
- Check if their balances are correct

**Example phrases:**
- *"Validate my balances"*
- *"Check my wallets against DeBank"*
- *"Are my TRES balances correct?"*
- *"Show me any discrepancies between TRES and on-chain data"*

---

## Prerequisites

| Requirement | Details |
|---|---|
| TRES Finance access | Must be authenticated via `get_viewer` |
| DeBank API key | Free key available at [cloud.debank.com](https://cloud.debank.com) |
| EVM wallets | At least one `0x...` wallet tracked in TRES |

---

## Process Overview

### Step 1 — Authenticate with TRES
Call `get_viewer` to confirm the organization name.

### Step 2 — Fetch wallets and balances from TRES

**IMPORTANT — Timeout handling:** The `internalAccount` query with both `balances` and `positions` will timeout for large orgs. Split into two separate queries:

**Query 1: Wallets + Balances only (no positions)**

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

> **Note:** The `amount` field is returned as a **string**, not a number. Always `float()` it before arithmetic.

**Wallet classification:**

| Type | Condition | Validated? |
|---|---|---|
| EVM | `0x...` address + EVM platform + `isExchange: false` | ✅ Yes |
| Exchange | `isExchange: true` | ❌ No |
| Non-EVM | Bitcoin, Tezos, Tron, etc. | ❌ No |
| Empty | No asset balances | ❌ No |

**Supported EVM platforms:** Ethereum, Arbitrum, Optimism, Polygon, Base, Avalanche, Binance, Gnosis Chain, zkSync, Fantom, Celo, Berachain, Linea, Scroll, Sonic, HyperEVM.

### Step 3 — Fetch DeFi positions from TRES

**Do NOT use the `positions` sub-field on `internalAccount`** — it returns all historical snapshots (can be 3000+ entries per wallet) and will timeout or exceed token limits.

Instead, use the dedicated `getStatelessWalletsPositions` query which returns **current** positions only:

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

**Required parameters:**
- `walletIdentifiers`: array of wallet addresses
- `platform`: must be an enum value like `ETHEREUM`, `POLYGON`, `ARBITRUM`, etc.

**Optional but recommended:**
- `application`: filter by protocol (e.g. `"aave-v3"`, `"verse"`, `"lido"`, `"merkl"`, `"uniswap-v4"`, `"sablier"`, `"ethena"`, `"stakewise"`, `"quickswap"`, `"steer"`, `"yieldnest"`, `"morphoblue"`)

**IMPORTANT:** Without the `application` filter, the query returns empty results. Always specify the application.

**Batching strategy:**
1. First, fetch DeBank `all_complex_protocol_list` for each wallet to discover which protocols have positions
2. Map DeBank protocol names to TRES application names (lowercase, hyphenated)
3. Use GraphQL aliases to batch multiple wallet+platform+application combos into a single query:

```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 }
  }
}
```

Keep each batched query to ~6 aliases max to avoid timeouts.

### Step 4 — Retrieve DeBank API key

Read `DEBANK_API_KEY` from plugin user config — do **not** ask the user to paste it in chat.
If the key is absent or empty, stop and display:

> "DEBANK_API_KEY is not configured. Please add it via the plugin settings (obtain your key at https://cloud.debank.com)."

### Step 5 — Fetch DeBank data via bash

For each EVM wallet, fetch **two** endpoints:

1. **Token balances:** `all_token_list` — covers all chains without requiring a `chain_id`
2. **DeFi protocol positions:** `all_complex_protocol_list` — returns LP, staking, lending positions with underlying token amounts

Use `--data-urlencode` with `-G` so the wallet address is never shell-interpolated into the URL string:

```bash
# 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"
```

**Fiat-value filter:** Discard any token where `price < 0.01` — these are excluded from all matching, display, and reporting.

**Rate limiting:** Add a 0.3s delay between wallet requests to avoid 429 errors.

### Step 6 — Match regular assets

Matching must be **chain-aware**. DeBank's `all_token_list` returns a `chain` field per
token (e.g. `"eth"`, `"arb"`,
eli5Skill

Explain a topic like I'm a 5 year old. Use when the user types /eli5 <topic> or asks for a dead-simple picture explainer of how something works.

quickdesignSkill

Use the `quickdesign` CLI to generate AI media — UGC promo videos, image edits, product creatives, video upscales — through Seedance, Kling, Sora2, Nano Banana, and GPT Image. Invoke this skill whenever the user asks for a talking-avatar video, multi-segment ad / promo / explainer, image edit (object swap, angle change, state change), product photoshoot, or video upscale via QuickDesign.

testdino-auditSkill

Use only when the user explicitly asks for a TestDino audit of Playwright automated test code. Routes through the audit tools the TestDino MCP server exposes (get_audit_report + submit_audit_report, or the legacy test_audit). For generic code review or non-Playwright targets, do a normal review instead.

testdino-healthSkill

Use when the user wants to check TestDino connection status, validate their PAT, discover available organizations and projects, or find the right projectId. Always call this first when the project context is ambiguous before any other TestDino tool.

testdino-manual-runsSkill

Use when the user wants to manage a manual execution run or update case-level results inside a run — listing runs, creating runs for a release, inspecting a run, assigning cases, or marking case results (passed/failed/blocked/skipped/retest/untested). Accepts counter-style IDs like RUN-12 and TC-156.

testdino-manual-testsSkill

Use when the user wants to create, update, or browse manual QA test cases and suites in TestDino — not execution runs. Covers list_manual_test_suites, list_manual_test_cases, get_manual_test_case, create_manual_test_case, update_manual_test_case, create_manual_test_suite.

testdino-releasesSkill

Use when the user wants to browse, inspect, create, or update releases/milestones in a TestDino project. Covers list_releases, get_release, create_release, and update_release. Accepts counter-style IDs like MS-12.

testdino-runsSkill

Use when the user wants to inspect automated test runs, list failed or flaky tests, debug a failing testcase with historical context, or filter runs by branch, commit, author, environment, browser, status, or tags. Includes list_testruns, get_run_details, list_testcase, get_testcase_details, and debug_testcase.