tres-asc845-swap-reprice-skill

$npx mdskill add anthropics/claude-plugins-community/tres-asc845-swap-reprice-skill

Reprice swap legs to ensure clearing accounts net to zero under ASC 845

  • Fixes non-zero residual balances in swaps/trade clearing accounts.
  • Deploys TRES Finance MCP server for GraphQL calls.
  • Automatically reprices swap inflow and outflow legs based on fair value.
  • Updates clearing account values to ensure net balance is zero.

SKILL.md

.github/skills/tres-asc845-swap-reprice-skillView on GitHub ↗
---
name: tres-asc845-swap-reprice-skill
description: >
  Reprice swap transaction legs under ASC 845 (Nonmonetary Transactions) to ensure clearing accounts
  net to zero. Use this skill whenever the user wants to: reprice swaps, fix clearing account residuals,
  apply equal-value exchange to swap legs, run setBatchUseCounterpartyFiatValue, zero out a clearing
  account, apply ASC 845, fix swap pricing mismatches, ensure no gain/loss on swaps, or close a month
  where a swaps/trade clearing account has a residual balance. Also trigger when the user mentions
  "counterparty fiat value", "swap repricing", "clearing account net to zero", or "equal value exchange".
compatibility: "Requires TRES Finance MCP connector"
---

# ASC 845 Swap Repricing Skill

## Purpose

Implements **equal-value exchange under ASC 845 (Nonmonetary Transactions)** for swap transactions
in TRES Finance. In a simultaneous swap, the fair value of the asset surrendered (outflow) is the
best evidence of the fair value of the asset received (inflow). This skill reprices inflow legs to
match outflow legs so that clearing accounts net to zero.

## When to Use

- A swaps/trade clearing account has a non-zero residual after month-end
- User wants to apply ASC 845 to a population of swap transactions
- User says "setBatchUseCounterpartyFiatValue" or similar

## MCP Server

All GraphQL calls use the **`user-tres-finance`** MCP server (`execute` tool).

Variable keys and nested input fields MUST use **camelCase** (e.g. `timestamp_Gte`, not `timestamp_gte`).

## Prerequisites

- TRES Finance MCP connection (`user-tres-finance`)
- The user must specify:
  1. **Target ERP account** — the clearing account to zero out (e.g. "Swaps Clearing Account", NS #818)
  2. **Transaction scope** — either a date range (timestamp_Gte / timestamp_Lte) or specific tx hashes
  3. **Confirmation** — user must approve before mutations are executed

## Workflow

### Step 1: Gather Parameters

Ask the user for:
- Target ERP account name or ID (the clearing account)
- Date range OR list of transaction hashes
- **Activity tags** (optional) — filter to only transactions with specific classification activities
  (e.g. "STAKING LOCKUP", "SWAP"). None, one, or many may be selected. If omitted, all activities
  are included. Use `tx_Classification_Activity_In` on the TRES query.
- Currency (default: USD)
- Whether to run in **dry-run** (preview only) or **execute** mode

### Step 2: Query Subtransactions

Use the TRES `subTransaction` query to fetch all subtransactions in scope. Include these fields:
```graphql
{
  id
  amount
  balanceFactor
  timestamp
  fiatValue
  isManualFiatValue
  belongsTo { id name }
  asset { assetClass { symbol } }
  tx { id identifier classification { activity } }
  flowRule {
    ruleName
    integrationAccount { name value }
  }
}
```

If activity tags were specified, pass them as `tx_Classification_Activity_In: ["STAKING LOCKUP", "SWAP"]`
on the query. Note: transactions with `classification: null` will be excluded when this filter is used,
so only apply it when the user explicitly requests it.

Paginate in batches of 50 (to avoid timeouts). Save the combined results to a JSON file for the orchestrator script.

### Step 3: Run the Orchestrator Script

From the skill `scripts/` directory, run `orchestrate_reprice.py` (handles MCP response shapes, account filter, preview, and mutation JSON):

```bash
cd "${CLAUDE_PLUGIN_ROOT}/skills/tres-asc845-swap-reprice-skill/scripts" && \
python3 orchestrate_reprice.py \
  --input /path/to/swap_reprice_input.json \
  --account-name "Swaps Clearing Account" \
  --output /path/to/reprice_plan.json \
  --mutations-output /path/to/reprice_mutations.json
```

Use `--account-value` instead of `--account-name` when filtering by ERP account number. Pass `--activity-tags SWAP "STAKING LOCKUP"` when the user requested activity filters.

The script prints a preview to stdout and writes:
- `reprice_plan.json` — full plan with per-transaction adjustments
- `reprice_mutations.json` — ready-to-execute `setManualFiatValue` variables

For lower-level repricing only (no orchestration), use `reprice_swaps.py` directly — see `scripts/reprice_swaps.py` for flags.

### Step 4: Repricing Logic (ASC 845)

The orchestrator implements the logic below. Read `scripts/reprice_swaps.py` for the canonical implementation.

The core principle: calculate the **difference** between total outflow fiat and total inflow fiat,
then distribute that difference across inflows **in proportion to their token amounts**. This
preserves the original pricing as a base and makes the minimum adjustment needed.

For each parent transaction:

**Case 1: One outflow, one inflow**
```
inflow.newFiatValue = outflow.fiatValue
```

**Case 2: One outflow, many inflows**
```
difference = outflow.fiatValue - sum(inflow.fiatValue for each inflow)
totalInflowTokens = sum(inflow.amount for each inflow)
for each inflow:
    tokenProportion = inflow.amount / totalInflowTokens
    inflow.newFiatValue = inflow.fiatValue + (difference * tokenProportion)
```

**Case 3: Many outflows, one inflow**
```
inflow.newFiatValue = sum(outflow.fiatValue for each outflow)
```

**Case 4: Many outflows, many inflows**
```
totalOutflowFiat = sum(outflow.fiatValue for each outflow)
totalInflowFiat = sum(inflow.fiatValue for each inflow)
difference = totalOutflowFiat - totalInflowFiat
totalInflowTokens = sum(inflow.amount for each inflow)
for each inflow:
    tokenProportion = inflow.amount / totalInflowTokens
    inflow.newFiatValue = inflow.fiatValue + (difference * tokenProportion)
```

**Worked example (Case 2):**
```
Before:  Outflow = 100 tokens @ $100 | Inflows = 25 tokens @ $25, 25 @ $25, 35 @ $35 (total $85)
         Difference = $100 - $85 = $15 | Total inflow tokens = 85

After:   Inflow 1: $25 + ($15 × 25/85) = $25 + $4.41 = $29.41
         Inflow 2: $25 + ($15 × 25/85) = $25 + $4.41 = $29.41
         Inflow 3: $35 + ($15 × 35/85) = $35 + $6.18 = $41.18
         Total inflows after = $100.00 ✓  (clearing account nets to zero)
```

**Edge cases:**
- If `totalInflowTokens == 0`, distribute the difference equally across inflows
- If a subtransaction already has `isManualFiatValue == true`, flag it for user review (it was already manually repriced)
- Skip transactions with only outflows or only inflows (not a complete swap)
- Last inflow in the group receives the remainder to absorb rounding (ensures exact match)

### Step 5: Preview the Reprice Plan

Present the orchestrator stdout summary and/or the plan JSON to the user:

```
TX Identifier | Outflow Total | Inflow Before | Inflow After | Adjustment
------------- | ------------- | ------------- | ------------ | ----------
0xabc...      | $1,234.56     | $1,230.00     | $1,234.56    | +$4.56
0xdef...      | $5,678.90     | $5,670.00     | $5,678.90    | +$8.90
```

Also show aggregate stats:
- Total transactions affected
- Total outflow fiat
- Total inflow fiat (before)
- Total inflow fiat (after)
- Net clearing account residual (before → after, should go to $0)
- Count of already-manually-priced subtxs being overwritten

### Step 6: Execute (with user confirmation)

**Never run mutations without explicit user confirmation.**

Only after the user confirms, execute `setManualFiatValue` for each inflow subtransaction (use variables from `reprice_mutations.json`):

```graphql
mutation SetManualFiatValue($id: ID!, $newFiatValue: String!, $currency: String) {
  setManualFiatValue(id: $id, newFiatValue: $newFiatValue, currency: $currency) {
    subTransaction {
      id
      fiatValue
      isManualFiatValue
    }
  }
}
```

Execute one at a time (not batch) to handle locked-period errors gracefully.
If `setBatchManualFiatValue` is preferred for speed, group inflows by asset
where a uniform per-unit price applies.

**Important**: `setManualFiatValue` takes `newFiatValue` as a string.
`setBatchManualFiatValue` takes `ids` (list) and `newUnitValue` (Float) and computes
`newUnitValue * amount` — only use this if all subtxs in the batch should have the same unit price.

### Step 7: Verify

Re-query the subtransactions and re-aggregate to confirm the clearing account now nets to zero.

## Error Handling

- **Locked period**: If a subtransaction is in a locked period, warn the user. They must unlock
  via `deleteLockedPeriod`, apply changes, then re-lock via `createLockedPeriod`.
- **Missing fiat values**: If outflow fiatValue is null, skip the transaction and flag it.
- **Zero-value legs**: If outflow total is $0, skip (nothing to propagate).
- **Already manual**: Flag but still overwrite — only after the user confirmed the batch.

## Script Reference

| Script | Role |
|--------|------|
| `scripts/orchestrate_reprice.py` | Primary entry — parse MCP JSON, filter, preview, write plan + mutations |
| `scripts/reprice_swaps.py` | Core ASC 845 repricing engine (imported by orchestrator; usable standalone) |

More from anthropics/claude-plugins-community

SkillDescription
eli5Explain 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.
html-planWrite an implementation plan as one interactive HTML page - a tree of claims (why › what › how › where), each proved by one exhibit (UI mockup, state machine, call stack, schema or code), with the decisions the user has to make placed on the claim they change. Use when the user types /html-plan, or asks for a plan, RFC or design before building something that touches more than a couple of files.
quickdesignUse 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-auditUse 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-healthUse 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-runsUse 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-testsUse 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-releasesUse 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-runsUse 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.
testdino-sessionsUse when the user wants to browse, inspect, create, or update exploratory testing sessions in TestDino — by state, status, session type, assignee, release, or tags. Covers list_sessions, get_session, create_session, and update_session. Accepts counter-style IDs like SES-12.