关于 walrus-quilts
walrus-quilts 是面向使用 Walrus 存储的开发者的技能,说明如何将多个小文件打包为一个存储单元,并通过标识符、标签或 QuiltPatchId 读取。内容涵盖 CLI、TypeScript SDK 与 HTTP API 的操作及适用场景。
主要功能
- 01将多个小文件打包为一个 quilt
- 02通过标识符、标签或 QuiltPatchId 读取
- 03介绍 CLI、TypeScript SDK 和 HTTP API
- 04说明整组 quilt 的生命周期限制
适用场景
- 01批量存储许多小文件以摊销元数据开销
- 02按标识符或标签检索 quilt 中的文件
- 03判断文件是否适合打包存储
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mystenlabs/ walrus-skills --skill walrus-quilts安装后在 Claude Code 中输入/walrus-quilts确认已加载。
附带文件evals/evals.json
详细介绍
Walrus 拼布
来源限制: 本技能的所有信息均来自 Walrus 拼布 CLI 文档和 拼布 HTTP API 文档。 扩展本技能时,只能引用这些来源。
拼布会将多个 blob 批量打包成一个 Walrus 存储单元,从而显著降低存储大量小文件的开销和成本。通过 QuiltPatchId 或标识符(而非标准 BlobId)检索拼布中的单个 blob。
本技能中的所有模式均源自:
如果不确定某项拼布操作,请先获取相关页面,再作答。
相关技能
| 主题 | 技能 | 在以下情况下加载 |
|---|---|---|
| CLI 基础 | walrus-cli | CLI 的常规安装、配置和单 blob 操作 |
| HTTP API 基础 | walrus-http-api | 单 blob 的 HTTP 存储/读取 |
| Blob 生命周期 | walrus-blob-lifecycle | 延长、删除、共享(适用于整个拼布) |
技能内容
关键概念
-
拼布。 一个包含多个 blob 的 Walrus 存储单元。在链上,拼布表示为一个
BlobSui 对象。存储成本按拼布总大小计算,而非按每个 blob 计算,因此存储大量小文件时可以节省开销。 -
QuiltPatchId。 拼布中每个 blob 的唯一 ID。它由拼布内容派生,因此,如果重新创建的拼布内容不同,blob 的
QuiltPatchId也会改变。它与标准BlobId不同。 -
标识符。 拼布中 blob 的易读名称(例如文件名)。标识符在拼布内必须唯一,且不能以下划线
_开头。字段名_metadata保留给 Walrus 原生元数据使用。 -
生命周期适用于整个拼布。 你无法删除、延长或共享拼布中的单个 blob。
delete、extend和share等操作适用于整个拼布。
选择指南
只有在所有条目都指向拼布时,拼布才是合适的选择;如果任何条目指向普通 blob,就应将该条目存储为普通 blob。
| 维度 | 适合使用拼布的情况 | 适合使用普通 blob 的情况 |
|---|---|---|
| 文件数量 | 可以批量处理的多个项目(数十到数百个,QuiltV1 最多 666 个) | 单个项目,或不会同时到达的多个项目 |
| 单项大小 | 每个项目都较小,通常低于 10 MiB | 某个项目接近每个 patch 约 4 GiB 的上限,或足够大,以至于开销可以忽略 |
| 生命周期 | 项目具有相同的生命周期(一起存储、延长、退役) | 某个项目需要单独安排删除、延长或共享 |
| 寻址方式 | 可以按标识符或标签查找 | 需要由内容派生的 BlobId;QuiltPatchId 取决于整个拼布 |
| 检索方式 | 单独读取项目,且读取频率不高 | 每个项目都是高频访问、独立缓存的对象 |
文档指出的注意事项:单文件拼布会引入 QuiltPatchId 间接寻址,却没有成本优势;将生命周期不匹配的项目分组,会迫使你为了生命周期最长的项目保留整个拼布;而需要通过内容哈希查找项目的应用,则需要使用普通 blob,或自行维护标识符到内容的映射。
TypeScript SDK
client.walrus.writeFiles({ files, epochs, deletable, signer }) 会将一次调用中的所有文件存储为一个拼布;getFiles({ ids })/getBlob({ blobId }).files({ identifiers | tags | ids }) 则可按标识符、标签或拼布 ID 读取 patch。参见 walrus-ts-sdk。
CLI:存储拼布### CLI:存储拼布
使用 --paths 从目录存储
# Store all files from a directory recursively
walrus store-quilt --epochs 5 --paths ./my-assets/
# Store from multiple directories
walrus store-quilt --epochs 10 --paths ./images/ ./documents/ ./data.json
文件名会成为标识符。所有标识符在拼布内都必须唯一。支持 glob 模式。
使用 --blobs 配合自定义标识符和标签进行存储
walrus store-quilt \
--blobs '{"path":"photo.jpg","identifier":"walrus","tags":{"color":"grey","size":"medium"}}' \
'{"path":"icon.png","identifier":"seal","tags":{"color":"grey","size":"small"}}' \
--epochs 5
如果省略 identifier 或将其设为 null,则使用文件名。
生命周期选项
与常规 walrus store 相同:--epochs、--earliest-expiry-time 或 --end-epoch。
CLI:从 quilt 中读取
按标识符读取
walrus read-quilt --out ./downloads/ \
--quilt-id <QUILT_BLOB_ID> --identifiers walrus.jpg another-walrus.jpg
按标签读取
# Download all blobs tagged with species=cat
walrus read-quilt --out ./downloads/ \
--quilt-id <QUILT_BLOB_ID> --tag species cat
按 QuiltPatchId 读取
walrus read-quilt --out ./downloads/ \
--quilt-patch-ids <PATCH_ID_1> <PATCH_ID_2>
列出 quilt 中的所有补丁
walrus list-patches-in-quilt <QUILT_BLOB_ID>
返回所有补丁及其标识符和 QuiltPatchId 值。
HTTP API:存储 quilt
通过 multipart 表单上传将 quilt 存储到发布端:
# Store 2 files with custom identifiers
curl -X PUT "$PUBLISHER/v1/quilts?epochs=5" \
-F "[email protected]" \
-F "[email protected]"
表单字段名称将成为标识符。常规 blob 查询参数(epochs、permanent、deletable、send_object_to)也适用于 quilt。
使用 Walrus 原生元数据标签存储
curl -X PUT "$PUBLISHER/v1/quilts?epochs=5" \
-F "[email protected]" \
-F "[email protected]" \
-F '_metadata=[
{"identifier": "quilt-manual", "tags": {"creator": "walrus", "version": "1.0"}},
{"identifier": "logo-2025", "tags": {"type": "logo", "format": "png"}}
]'
存储响应
响应包含 quilt 的 blobId 和各个 storedQuiltBlobs,其中包含 quiltPatchId 值:
{
"blobStoreResult": {
"newlyCreated": {
"blobObject": {
"id": "0xe6ac...bc02",
"blobId": "6XUOE-Q5-nAXHRifN6n9nomVDtHZQbGuAkW3PjlBuKo",
"size": 1782224,
"storage": { "startEpoch": 103, "endEpoch": 104, "storageSize": 72040000 },
"deletable": false
},
"cost": 12075000
}
},
"storedQuiltBlobs": [
{ "identifier": "another_walrus.jpg", "quiltPatchId": "6XUOE-...BAQD..." },
{ "identifier": "walrus.jpg", "quiltPatchId": "6XUOE-...B0AB..." }
]
}
HTTP API:从 quilt 中读取
# Read by QuiltPatchId
curl "$AGGREGATOR/v1/blobs/by-quilt-patch-id/<PATCH_ID>"
# Read by quilt ID + identifier
curl "$AGGREGATOR/v1/blobs/by-quilt-id/<QUILT_BLOB_ID>/walrus.jpg"
目前每个请求仅支持读取一个 blob。尚不支持在单个请求中从 quilt 批量检索。
响应标头
这两种方法都会返回原始 blob 字节。元数据通过 HTTP 标头返回:
X-Quilt-Patch-Identifier:blob 在 quilt 中的标识符ETag:用于缓存的补丁 ID 或 quilt ID
何时使用 quilt,何时使用单个 blob
| 场景 | 建议 |
|---|---|
| 许多小文件(每个 <10 MB) | Quilt。 每个单独的 blob 都有约 64 MB 的元数据开销。Quilt 可将这部分开销分摊到所有文件上。 |
| 大量小型 JSON 文档 | Quilt。 对微小 blob 单独调用存储接口,成本效率很低。 |
| 一个大文件(>10 MB) | 单个 blob。 为单个文件使用 quilt 没有好处。 |
| 需要独立生命周期的文件 | 单个 blob。 你无法在 quilt 中删除或延长单个文件的生命周期。 |
| 静态网站资源 | Quilt。 Walrus Sites 内部也因此使用 quilt。 |
每个 blob 的元数据开销意味着,单独存储一个 1 KB 的 JSON blob,成本与存储一个 64 MB 文件大致相同。Quilt 会将所有内容打包成一个存储单元,从而消除这项开销。
规则
- 一个 quilt 中的标识符必须唯一。 标识符重复会导致存储操作失败。
- 标识符不能以下划线
_开头。_metadata字段名保留给 Walrus 原生元数据使用。 - 生命周期操作适用于整个 quilt。 你无法删除、延长或分享 quilt 中的单个 blob。
- QuiltPatchId 不是 BlobId。 blob 的
QuiltPatchId专属于其所属的 quilt。同一文件内容存放在另一个 quilt 中时,会获得不同的QuiltPatchId。 - 许多小文件应使用 quilt。 Quilt 可降低每个 blob 的开销。对于单个大文件,请使用常规
walrus store。 - 内容寻址仍然适用。 相同的 quilt 内容始终会生成相同的 quilt blob ID。
常见错误
- 尝试从 quilt 中删除单个 blob。 你必须删除整个 quilt,无法移除单个 blob。
- 使用 BlobId 从 quilt 中读取。 Quilt 中的 blob 使用
QuiltPatchId或identifier标识,而不是标准的BlobId。 - 不同目录中存在重复文件名。 使用
--paths指定多个目录时,如果两个文件同名,标识符就会冲突,导致存储失败。 - 期望 HTTP 批量读取。 目前通过 HTTP 读取 quilt 时,每个请求仅支持一个 blob。
- 将许多小 blob 单独存储,而不是存为 quilt。 这是最常见的成本错误。每个单独的 blob 都会产生约 64 MB 的元数据开销。将 100 个小型 JSON 文件单独存储,成本大约是将它们打包到同一个 quilt 中的 100 倍。