tres-tx-story について
トランザクションハッシュから TRES Finance の取引を取得し、資産の動きを図示して平易な言葉で説明するスキルです。SVG フロー図と簡潔な取引説明を組み合わせます。
主な機能
- 01ハッシュによる取引検索
- 02取引・資産の詳細抽出
- 03SVG フロー図の描画
- 04資産移動の平易な説明
- 05取引データ不足への対応
活用シーン
- 01トークンスワップや送金の把握
- 02ウォレットの入出金とガスの確認
- 03会計担当者以外への取引説明
MCP 対応
`https://ai.tres.finance/mcp` の TRES Finance MCP サーバーを使って認証し、取引データを取得します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ anthropics/ claude-plugins-community --skill tres-tx-storyインストール後、Claude Code で/tres-tx-storyを入力して読み込まれたか確認します。
詳細
TRES Transaction Story
TRES Finance からハッシュでトランザクションを取得し、すべての資産移動をフロー図にして、何が起きたかを平易な英語で説明します。
MCP サーバー
すべての呼び出しには TRES Finance MCP サーバー(URL:https://ai.tres.finance/mcp)を使用します。
ステップ 1 — 認証
セッションを確認するため、引数なしで get_viewer を呼び出します。
ステップ 2 — トランザクションを取得する
ハッシュを identifier として指定し、トランザクションを検索します。
query GetTransactionByHash($hash: String!, $currency: String) {
transaction(identifier: $hash, currency: $currency, limit: 1) {
results {
id
identifier
platform
timestamp
success
decodedFunctionName
methodId
fromAddress { identifier displayName isInternal customAccountName }
toAddress { identifier displayName isInternal customAccountName }
contract { identifier contractName protocols applications }
classification { activity action functionName }
ledgerSummary
applications
protocols
internalAccounts { id name }
children {
id
amount
balanceFactor
platform
type
fiatValue
nonTaxableType
isInternalTransfer
financialActionGroup
belongsTo { id name identifier }
sender { identifier displayName isInternal customAccountName }
recipient { identifier displayName isInternal customAccountName }
asset {
identifier
symbol: key
assetClass { id symbol verificationStatus }
}
}
}
}
}
変数:{ "hash": "<user_provided_hash>", "currency": "usd" }
フォールバック:
identifierで結果が 0 件の場合は、ハッシュの末尾 20 文字を使ってidentifier_Containsで再試行します。一部のチェーンではハッシュが0xプレフィックスなしで保存されていることがあります。まだ結果が空の場合は、プレフィックスを取り除いて再試行してください。
ステップ 3 — データを解析する
結果から以下の項目を抽出します。
| フィールド | 目的 |
|---|---|
identifier | トランザクションハッシュ |
platform | ブロックチェーン(ETHEREUM、SOLANA など) |
timestamp | 日時 |
success | 成功したかどうか |
decodedFunctionName | 呼び出されたスマートコントラクト関数 |
fromAddress / toAddress | 最上位の送信元 → 送信先 |
contract.contractName | 関連するスマートコントラクト(ある場合) |
classification.activity + .action | TRES の分類ラベル |
children[] | 各サブトランザクション(個々のトークン移動) |
各子サブトランザクションから、以下を抽出します。
asset.assetClass.symbol— トークンシンボル(例:ETH、USDC)amount— 移動量fiatValue— 米ドル相当額balanceFactor—1= 流入、-1= 流出belongsTo.name— この移動が属する内部ウォレットsender.identifier/recipient.identifier— 取引相手type— GAS、TOKEN_TRANSFER など
ステップ 4 — 図を描画する
show_widget ツール(Visualizer)を使用して、インライン SVG 図を含む HTML ウィジェットを描画します。
描画前チェックリスト — SVG 要素を 1 つでも書く前に実施してください
A. すべてのラベル文字列を先に準備する
各矢印ラベル(トークン量 + シンボル)に、以下の書式ルールを適用します。
- 金額を書式設定します。
- amount ≥ 1,000,000 →
"1.2M"の形式(小数 1 桁) - amount ≥ 1,000 →
"264K"または"12,233"(カンマ区切りの整数) - amount ≥ 1 → 小数点以下最大 2 桁に丸める
- amount < 1 → 有効数字 4 桁まで保持します(例:
"0.033")
- amount ≥ 1,000,000 →
- シンボルを切り詰めます。
- symbol が 6 文字以下 → そのまま使用(ETH、USDC、DAI、CRV)
- symbol が 7~10 文字 → 完全なラベルが収まる場合のみそのまま使用します(手順 3 を参照)
- symbol が 10 文字を超える、
+を含む、または複合 LP トークンである →"LP tokens"に置き換えます
- ラベル全体の長さを測ります。
label = amount + " " + symbol。文字数を数え、7 を掛けます。これがピクセル幅です。 - ラベルに使用できるスペース = 矢印の x 方向の幅から安全マージン 20px を引いた値です。
- 左側の間隔(ウォレット→コントラクト):x は 136 から 248 まで → 幅 = 112px → ラベルの最大文字数 = 13
- 右側の間隔(コントラクト→ウォレット):x は 408 から 504 まで → 幅 = 96px → ラベルの最大文字数 = 11
label_px_width > available_spaceの場合は、さらに短縮します。金額を有効数字 1 桁に省略するか、それでも長すぎる場合はシンボルだけにします。
B. 矢印の数を数え、SVG の高さを計算する
- ガス以外の矢印(流出 + 流入)の数を数えます。これを
Nとします。 - 矢印の各行には縦方向に 34px のスペースを割り当てます。
- ノードの中心 Y = 50 + (N × 34) / 2(矢印がノードの中心を基準に対称に広がるようにします)。
- ガス矢印は左側のウォレットの円の下端から 60px 下に配置します。
- SVG の高さ = node_centre_y + node_radius + 80(ガス矢印 + ラベル + 余白)。
- SVG の高さは最低 230px とします。
C. 矢印の Y 位置を配置する
- 矢印を node_centre_y を中心に、34px 間隔で均等に配置します。
- 最初の矢印の y = node_centre_y - ((N-1) × 34) / 2
- 以降の矢印はそれぞれ y += 34
- 流出矢印(ウォレット → コントラクト)は図の左半分を使用します。
- 流入矢印(コントラクト → ウォレット)は右半分を使用します。
- 流入がちょうど 1 本で、流出が複数ある場合、流入矢印は node_centre_y に配置します。
固定のノード位置(変更しないでください)
ViewBox width: 640
Left wallet circle: cx=90, cy=node_centre_y, r=46
Contract rect: x=248, y=node_centre_y-55, width=160, height=110, rx=12
Right wallet circle: cx=550, cy=node_centre_y, r=46
Arrow x coordinates:
Outflow (left→centre): x1=136, x2=246 midpoint_x=191
Inflow (centre→right): x1=410, x2=504 midpoint_x=457
Gas (downward): x1=x2=90, y1=node_centre_y+46
これらの x 値はノードの端から導き出されたもので、調整してはいけません。これにより、ラベルは常にノード間の空きスペースに配置されます。
矢印ラベルの配置ルール(例外なし)
Label x = midpoint_x of arrow (191 for outflows, 457 for inflows)
Label y = arrow_y - 12
text-anchor = "middle"
font-size = 10.5px
font-weight = 500
ラベルを別のラベルと同じ y に配置してはいけません。 2 本の矢印がわずか 34px 離れている場合、ラベル(y-12)の間隔も 34px あり、それで十分です。2 つのラベルを同じ y 座標に重ねてはいけません。
ノードの端に近いラベルに text-anchor="start" を使ってはいけません。 常に x の中点を基準に "middle" で配置してください。
ノード内テキストのルール
ウォレットの円(r=46、テキストを配置できる範囲 = 中心から±36px):
Line 1 (name): y = cy - 8, font-size=11, font-weight=500
Line 2 (address): y = cy + 7, font-size=9.5, font-family=monospace
Line 3 (role): y = cy + 21, font-size=9
最大 3 行です。各行は円の幅(その y での弦の長さは約 80px、9px で約 11 文字、10px で約 9 文字)に収めてください。10 文字を超えるウォレット名は省略してください。
コントラクトの長方形(幅=160、高さ=110):
Line 1 (name): y = rect_top + 28, font-size=11, font-weight=500
Line 2 (subname): y = rect_top + 44, font-size=10
Line 3 (function): y = rect_top + 60, font-size=9.5
Line 4 (address): y = rect_top + 76, font-size=9, font-family=monospace
Line 5 (type): y = rect_top + 92, font-size=9
最大 5 行です。各行は x=328 を中心にしてください。テキストは幅 152px(160 - 両側のパディング各 8px)に収めてください。9px では最大約 21 文字です。それより長いテキストは省略してください。
ガス矢印のルール
- 常に垂直にし、左側のウォレット円の下端から下向きに配置します。
- x1 = x2 = 90(ウォレットの cx と同じ)
- y1 = node_centre_y + 46 + 2(円の端から 2px 下)
- y2 = y1 + 55
- ラベル:線の右側に配置します。
x=98, y=(y1+y2)/2, text-anchor="start" - 矢印の先端の下に、小さなピルを追加します。x=90 を中心に、ラベル「network fee」を入れた rect を配置します。
- ガスラベルの最大長:「0.033 ETH gas」は 13 文字です。常に収まります。
色分け
| 要素 | 塗りつぶし | 線/色 |
|---|---|---|
| 内部ウォレット(送信元) | #EAF3DE | #639922 |
| 内部ウォレット(受信側) | #dcfce7 | #16a34a |
| スマートコントラクト | #EEEDFE | #7F77DD |
| 流出矢印 | — | #dc2626 |
| 流入矢印 | — | #16a34a |
| ガス矢印 | — | #ea580c |
| 流出ラベルのテキスト | — | #dc2626 |
| 流入ラベルのテキスト | — | #16a34a |
| ガスラベルのテキスト | — | #ea580c |
アニメーション
@keyframes flowDash { to { stroke-dashoffset: -40; } }
@keyframes fadeUp { from { opacity:0; transform:translateY(14px); } to { opacity:1; transform:translateY(0); } }
Outflow arrows: stroke-dasharray:8 5; animation: flowDash 1.1s linear infinite;
Inflow arrows: stroke-dasharray:8 5; animation: flowDash 1.1s linear infinite;
Gas arrow: stroke-dasharray:4 4; animation: flowDash 1.7s linear infinite;
Cards/sections: opacity:0; animation: fadeUp .5s ease forwards; (staggered delays)
ヘッダー
バッジのピルを使わず、プレーンテキストを 1 行で表示します:
[hash-pill: 0xABCD...1234] Chain · Date · function() · ✓ success
ハッシュのピルのスタイル:等幅フォント、11px、bg-secondary、枠線、border-radius 6px、パディング 4px 10px。 それ以外:12px、color-text-secondary。成功マーク:color-text-success、font-weight 500。
統計カード(図の下)
3 列のグリッドで、カードはそれぞれ送金総額(赤)、受取総額(緑)、支払ったガス代(オレンジ)を表示します。
値は次の形式にします:−$272,910/264K LP/0.127 ETH。12 文字以内にしてください。
サブラベル:11px、控えめな色。資産が複数ある場合はトークンの内訳を表示します。
フッターのルートカード
[function() badge] via ContractName · [protocol tag] [protocol tag] [Explain X ↗ button]
関数バッジ:黄色の背景 #FEF9C3、テキスト #854d0e、border-radius 6px。
プロトコルタグ:bg-secondary、枠線、border-radius 4px、11px。
ボタン:sendPrompt('How does [ContractName/protocol] work?') を呼び出します。
ステップ 5 — 平易な言葉での説明
図の後に、簡単で専門用語を使わない言葉で、短い説明を 3~6 文で書いてください。次の内容を含めます。
- 何が起きたか:中心となる操作(スワップ、送金、入金、ステーキングなど)
- 誰が関与したか:ウォレットとコントラクトを平易な言葉で説明します
- 何が移動したか:どの資産が、どちら向きに移動したか
- 最終結果:組織のウォレットに最終的に何が残ったか、または何を支払ったか
語調:暗号資産には詳しいものの、会計には詳しくない人に説明するイメージです。 「balanceFactor」「sub-transaction」「FIFO」のような専門用語は避けてください。「送った」「受け取った」「ガス代として支払った」「X を Y に交換した」などの表現を使います。
例:
これは Uniswap でのトークンスワップでした。あなたのウォレット(Main Treasury)は 1,000 USDC を Uniswap V3 ルーターコントラクトに送り、コントラクトから 0.412 ETH(約 $1,020 相当)を受け取りました。 また、Ethereum ネットワークにガス代として 0.003 ETH(約 $7.40)を支払いました。 最終的に、1 ETH あたりおよそ $2,476 でステーブルコインを ETH に交換しました。
エラー処理
| 状況 | 対応 |
|---|---|
| トランザクションが見つからない | TRES でハッシュが見つからなかったことをユーザーに伝えます。ハッシュを確認するか、別のハッシュを試すか尋ねます。 |
| 子トランザクションがない(サブトランザクションが空) | ヘッダーのみを表示し、「記録された資産の移動はありません。トランザクションが失敗したか、コントラクトのみとのやり取りだった可能性があります。」と注記します。 |
| 法定通貨の値が不明 | USD を表示せずに金額を表示し、「一部の資産では USD 換算額を取得できません。」と注記します。 |
| 認証エラー | TRES への接続を確認し、再認証するようユーザーに伝えます。 |