关于 tres-import-contacts
tres-import-contacts 是用于将 CSV 或 XLSX 中的地址标签导入 TRES 通讯录的技能,适合需要批量整理联系人信息的用户。它会校验并去重数据,并在导入前提供预览。
主要功能
- 01解析 CSV 和 XLSX 文件
- 02按地址去重并校验字段
- 03导入联系人名称与标签
- 04导入前展示数据预览
- 05处理重复项及导入失败
适用场景
- 01将填写好的地址映射表导入 TRES
- 02为多个区块链地址添加联系人名称
- 03批量更新联系人标签
MCP 相关
通过 user-tres-finance MCP 服务的 execute 工具调用 GraphQL,以查询会话和写入 TRES 通讯录联系人及标签。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ anthropics/ claude-plugins-community --skill tres-import-contacts安装后在 Claude Code 中输入/tres-import-contacts确认已加载。
详细介绍
TRES Finance — 从 CSV/XLSX 导入联系人
目标
读取用户提供的 CSV 或 XLSX 文件,其中包含地址到名称的映射,并将其作为联系人导入 TRES 地址簿。这是联系人工作流的后半部分:用户之前通过导出技能导出了未识别的地址,填写了名称和标签,现在希望将这些标签导入 TRES。
MCP 服务
所有 GraphQL 调用均使用 user-tres-finance MCP 服务(execute 工具)。
预期文件格式
文件应包含以下列(按列标题名称进行不区分大小写的匹配):
| 联系人名称 | 联系人地址 | 联系人标签 |
|---|---|---|
| Binance 热钱包 | 0xABC... | 交易所 |
| Vendor X | 0xDEF... | 供应商 |
- 联系人名称 — 分配给地址的标签(导入时必填;没有名称的行将被跳过)
- 联系人地址 — 区块链地址(必填)
- 联系人标签 — 联系人的可选标签。多个标签可以用逗号分隔(例如
Exchange, Custodian)
列的顺序不限 — 此技能会根据列标题名称进行匹配。文件可以包含其他列(例如导出技能中的“地址详情”补充列),这些列会被忽略。
工作流
步骤 1 — 身份验证
调用 get_viewer(不带参数)以确认会话处于活动状态,并记录组织名称。
步骤 2 — 读取并解析文件
用户会提供 CSV 或 XLSX 文件。根据文件扩展名检测格式。
对于 XLSX 文件:
使用 Python 和 openpyxl==3.1.5。如果未安装,请停止并显示:
"openpyxl is not installed. Please run:
python3 -m venv .venv && .venv/bin/pip install openpyxl==3.1.5"
- 如果工作簿有多个工作表,请查找名为 "Contacts" 的工作表(不区分大小写)。如果未找到,则使用第一个工作表。
- 读取标题行,查找“联系人名称”、“联系人地址”和“联系人标签”列的索引(不区分大小写匹配,并去除空白字符)。
- 读取所有数据行。
- 过滤掉末尾的空行 — openpyxl 有时会在工作表底部读取到多余的
None行。跳过所有单元格均为None或空字符串的行。
对于 CSV 文件:
使用 Python 内置的 csv 模块。
- 使用
encoding='utf-8-sig'打开文件,以处理 Excel 保存 CSV 时添加的 BOM(字节顺序标记)。否则,第一个标题可能显示为\ufeffContact Name,导致匹配失败。 - 首先尝试使用逗号作为分隔符。如果标题行不包含预期列,则改用分号分隔符重试(常见于欧洲区域设置下的 Excel 导出)。
- 读取标题行以查找列索引,匹配逻辑同上。
- 读取所有数据行。
步骤 3 — 验证并筛选
对于每一行:
- 如果联系人名称为空或缺失,则跳过 — 用户尚未识别此地址,因此无需导入。
- 如果联系人地址为空或缺失,则跳过 — 无法为不存在的地址添加标签。
- 对名称、地址和标签值去除空白字符。
- 解析标签:如果联系人标签包含逗号,则拆分为多个标签。去除每个标签的首尾空白字符,并移除空字符串。
- 按地址去重(不区分大小写):如果同一地址出现多次,则保留最后一次出现的记录(用户很可能已修正记录)。提示用户存在重复项。
筛选后,向用户报告:
- 文件中的总行数
- 跳过的行数(名称为空)
- 待导入的行数
- 发现的重复项
然后显示前 10 条待导入记录的预览表格(地址、名称、标签),并在继续前征求用户确认。
第 4 步 — 检查现有联系人(仅适用于 50 行及以上的导入)
对于小型导入(少于 50 行),跳过此步骤,直接开始导入——仅为少数联系人获取整个通讯录会造成不必要的延迟。
对于较大的导入,获取当前通讯录,以识别哪些地址已有标签。这有助于用户了解哪些联系人将被新建,哪些将被更新。
query AddressBook($limit: Int, $offset: Int) {
customAccountNameLabel(limit: $limit, offset: $offset) {
results {
originalIdentifier
labelValue
tags
}
totalCount
}
}
每次获取 500 条,分页遍历所有结果。构建一个以 originalIdentifier.lower() 为键的查找字典。
将导入列表与之比对,并报告:
- 新联系人 — 当前通讯录中不存在的地址
- 更新 — 已存在、但将获得新名称或标签的地址
重要:setCustomAccountNameLabelTags 是替换操作,而非追加。如果某个联系人当前的标签为 ["Exchange", "Custodian"],而导入文件中是 ["Vendor"],旧标签将被覆盖。对于任何已有标签且即将更新的联系人,请向用户发出警告。
继续操作前,先向用户展示此明细。如果有更新,请列出几个示例,展示旧名称 → 新名称,供用户检查确认。
第 5 步 — 导入联系人
对每一行通过验证的数据,调用两次 API:
5a. 设置联系人名称:
mutation SetContactName($identifier: String, $labelValue: String) {
setCustomAccountName(identifier: $identifier, labelValue: $labelValue) {
accountTxsSummary {
accountIdentifier
displayName
}
}
}
变量:
{
"identifier": "<the address>",
"labelValue": "<the contact name>"
}
5b. 设置标签(仅当该行包含标签时):
mutation SetContactTags($identifier: String!, $tags: [String]!) {
setCustomAccountNameLabelTags(identifier: $identifier, tags: $tags) {
accountTxsSummary {
accountIdentifier
displayName
}
}
}
变量:
{
"identifier": "<the address>",
"tags": ["Exchange", "Custodian"]
}
**批处理策略:**API 没有批量端点。对于小型导入(少于 20 个联系人),并行执行所有名称变更,然后并行执行所有标签变更——这样既快速又安全。对于较大的导入,每批并行处理 10 次调用,避免 API 负载过高,并每处理 25 个联系人向用户显示一次进度(例如:“已导入 25/142……”)。
**错误处理:**如果某个地址的变更失败,记录错误并继续处理下一行。不要中止整个导入。汇总所有失败项,以便生成摘要。
第 6 步 — 摘要
所有变更完成后,提供摘要:
- 成功导入的联系人总数(已设置名称)
- 已设置标签的联系人总数
- 任何失败项(列出地址和错误消息)
如果有失败项,建议用户使用同一文件再次运行此技能进行重试——已导入的联系人只会被更新(名称变更操作具有幂等性)。
边缘情况
- 文件没有标题行:如果首行不包含可识别的列名,请告知用户预期的格式,并让他们修正文件。
- 文件列不正确:如果找不到“Contact Address”列,则文件不可用。请报告找到的列以及预期的列。
- 文件为空:如果文件有标题但没有数据行,请告知用户。
- 所有名称均为空:如果每一行的 Contact Name 都为空,请告知用户——他们可能误传了未填写的模板。
- 文件非常大(>500 行):提醒用户这需要一些时间,并征求确认。
- 名称中含有特殊字符:原样传递——TRES 能处理标签中的 Unicode。
- 地址大小写混杂:
setCustomAccountNamemutation 接受原样传入的地址。不要统一大小写——传递文件中的原始值。 - 标签含有多余空格:
" Exchange , Custodian "→ 修剪为["Exchange", "Custodian"]。 - 地址未出现在任何交易中:即使 TRES 从未在交易中见过这些地址,mutations 也能正常工作——它们会创建相应的地址簿条目。
- 标签会被覆盖:
setCustomAccountNameLabelTags会完全替换现有标签。如果用户只想添加标签,需要先与现有标签合并(此技能不会自动执行此操作——它会直接替换)。更新已有标签的联系人时,请提醒用户这一点。 - CSV BOM 前缀:由 Excel 保存的 CSV 包含 UTF-8 BOM(
\ufeff),会破坏第一列的列标题。始终使用encoding='utf-8-sig'打开 CSV。 - 分号分隔的 CSV:欧洲地区的 Excel 导出文件使用
;而非,。如果按逗号解析时未找到预期的标题,请改用分号重试。 - XLSX 文件末尾的空行:openpyxl 会读取工作表末尾的空行。跳过所有值均为
None或空字符串的行。