关于 walrus-http-api
walrus-http-api 是通过 REST 接口接入 Walrus 的技能,适用于能发送 HTTP 请求的各类语言应用。它说明写入与读取服务的分工、上传方式和响应处理。
主要功能
- 01通过 HTTP PUT 存储 Blob
- 02通过 HTTP GET 读取 Blob
- 03说明 Publisher 与 Aggregator 分工
- 04设置存储周期与是否可删除
- 05读取字节范围和属性
- 06处理赞助式上传
适用场景
- 01为 HTTP 应用接入 Walrus 存储
- 02通过 Aggregator 提供 Blob 内容
- 03用字节范围支持浏览器视频定位
- 04为无钱包用户接收上传
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mystenlabs/ walrus-skills --skill walrus-http-api安装后在 Claude Code 中输入/walrus-http-api确认已加载。
附带文件evals/evals.json
详细介绍
Walrus HTTP API
来源限制: 本技能中的所有信息均来自 Walrus HTTP API 文档。 扩展本技能时,只能参考这些来源。
Walrus 通过发布者(写入)和聚合器(读取)服务提供 REST API。对于任何语言,这是最简单的集成方式:使用 HTTP PUT 存储 blob,使用 HTTP GET 读取 blob。无需安装 SDK。
本技能中的所有模式均源自:
如果不确定某个端点,请先获取相关页面再作答。
相关技能
| 主题 | 技能 | 适用场景 |
|---|---|---|
| Quilt HTTP 端点 | walrus-quilts | 通过 HTTP 存储或读取批量 blob |
| CLI | walrus-cli | 使用 walrus 二进制文件,而非 HTTP |
| TypeScript SDK | walrus-ts-sdk | 使用官方 TS SDK |
| Blob 管理 | walrus-blob-lifecycle | 扩展、删除或共享 blob |
| 加密 | walrus-data-security | 存储前加密 |
技能内容
关键概念
-
发布者。 一种 HTTP 服务,可接收 blob 数据并处理编码、分片分发和链上注册。向发布者发送 PUT 请求即可存储数据。Mainnet 上没有公开且无需身份验证的发布者。在 Mainnet 上,请运行自己的经身份验证的发布者、使用上传中继,或直接使用 TypeScript SDK。公开发布者端点仅适用于 Testnet。
-
聚合器。 一种 HTTP 服务,可从 Walrus 存储节点读取 blob,并通过 GET 请求返回。聚合器是只读的,可置于 CDN 前端。
-
Blob ID 与 object ID。 Blob ID 用于标识内容。Sui object ID 用于标识链上的
Blob对象。两者均可用于读取。通过 object ID 读取还支持 HTTP 标头属性。 -
一致性检查。 聚合器会在读取时验证 blob 的完整性。可使用
?strict_consistency_check=true启用严格检查;如果已知且信任写入者,也可使用?skip_consistency_check=true跳过检查。
存储 blob(发布者)
使用 HTTP PUT 向发布者存储数据:
# Store a string for 1 epoch (default)
curl -X PUT "$PUBLISHER/v1/blobs" -d "some string"
# Store a file for 5 epochs
curl -X PUT "$PUBLISHER/v1/blobs?epochs=5" --upload-file "some/file"
查询参数
| 参数 | 效果 | 默认值 |
|---|---|---|
epochs | 存储周期数 | 1 |
deletable=true | 所有者可在到期前删除 blob | 新 blob 的默认值 |
permanent=true | 到期前不可删除 blob | 必须显式指定 |
send_object_to | 将生成的 Blob Sui 对象发送到另一地址(赞助上传时,如何将所有权交给没有钱包的用户) | 发布者的钱包 |
reuse_resources=true | 复用发布者钱包已拥有的存储对象或 blob 对象,而非注册新的对象 | false;多个并发存储操作共用一个钱包时,请保持关闭 |
# Store as permanent for 5 epochs
curl -X PUT "$PUBLISHER/v1/blobs?epochs=5&permanent=true" --upload-file "file.dat"
# Store and send the blob object to another address
curl -X PUT "$PUBLISHER/v1/blobs?send_object_to=$ADDRESS" --upload-file "file.dat"
存储响应:新建
首次存储 blob 时:
{
"newlyCreated": {
"blobObject": {
"id": "0xe91e...c50",
"registeredEpoch": 34,
"blobId": "M4hsZGQ1oCktdzegB6HnI6Mi28S2nqOPHxK-W7_4BUk",
"size": 17,
"encodingType": "RS2",
"certifiedEpoch": 34,
"storage": {
"id": "0x4748...5faf",
"startEpoch": 34,
"endEpoch": 35,
"storageSize": 66034000
},
"deletable": false
},
"resourceOperation": {
"registerFromScratch": {
"encodedLength": 66034000,
"epochsAhead": 1
}
},
"cost": 132300
}
}
存储响应:已认证
相同内容已存在且剩余有效期足够时:
{
"alreadyCertified": {
"blobId": "M4hsZGQ1oCktdzegB6HnI6Mi28S2nqOPHxK-W7_4BUk",
"event": {
"txDigest": "4XQHFa9S324wTzYHF3vsBSwpUZuLpmwTHYMFv9nsttSs",
"eventSeq": "0"
},
"endEpoch": 35
}
}
event 字段包含 Sui 事件 ID,可用于在 Suiscan 上查找交易。
读取 blob(聚合器)
使用 HTTP GET 从聚合器读取 blob:
# Read by blob ID
curl "$AGGREGATOR/v1/blobs/<BLOB_ID>" -o output.file
# Read by Sui object ID (also returns HTTP header attributes)
curl "$AGGREGATOR/v1/blobs/by-object-id/<OBJECT_ID>" -o output.file
通过 object ID 读取时,会识别以下属性键,并将其作为 HTTP 标头返回:content-disposition、content-encoding、content-language、content-location、content-type 和 link。
发布器、聚合器和上传中继:如何选择
| 服务 | 方向 | 主网可用性 | 是否需要钱包 |
|---|---|---|---|
| 发布器 | 写入(PUT) | 没有公共发布器。请运行自己的发布器,或使用上传中继 / SDK。 | 是(WAL + SUI) |
| 上传中继 | 写入(PUT) | https://upload-relay.mainnet.walrus.space | 是(WAL + SUI + 可选小费) |
| 聚合器 | 读取(GET) | 有许多公共聚合器,无费用,无需钱包。 | 否 |
- 主网聚合器(Mysten Labs):
https://aggregator.walrus-mainnet.walrus.space - 测试网聚合器(Mysten Labs):
https://aggregator.walrus-testnet.walrus.space - 测试网发布器(Mysten Labs):
https://publisher.walrus-testnet.walrus.space
公共聚合器的完整列表可在 docs.wal.app/operators.json(JSON)和公共服务页面中查看。公共聚合器会设置 CORS 标头,因此浏览器可以直接读取。
由他人赞助的上传和无需钱包的上传
大多数用户既没有 SUI,也没有 WAL。Walrus 没有内置的 Gas 赞助机制;赞助意味着由你的某个钱包执行存储操作并付费。以下是三种模式:
| 模式 | 谁签名 | 谁付费 | 用户是否无需钱包 | 最适用于 |
|---|---|---|---|---|
| 后端发布器 | 发布器钱包 | 应用 | 是 | 接受 HTTP 原始字节并支付存储费用的后端 |
| 上传中继 | 客户端或应用签名者 | 客户端或应用签名者,另加中继小费(如已配置) | 仅当应用管理签名时 | 无法打开大量节点连接的浏览器和移动客户端 |
| 直接使用 SDK | 代码配置的签名者 | 应用钱包 | 是,前提是后端持有签名者 | 直接集成 Walrus 并在代码中控制签名的后端 |
参考架构:客户端使用你自己的凭据向后端进行身份验证;后端应用策略(配额、大小、时长),并将字节转发给你的发布器;发布器使用其已注资的钱包存储数据,并通过 send_object_to=<address> 将 Blob 对象发送给用户;后端返回 Blob ID。每次存储都会消耗真实的 WAL 和 SUI(在一个交易中预留 + 注册,在第二个交易中认证);没有免费套餐。
文档中提到的运营注意事项:
- 切勿在主网上公开未经过身份验证的发布器。 任何能够访问它的人都能花费你钱包中的 SUI 和 WAL。请在其前面设置经过身份验证的发布器 JWT 流程或你自己的网关。
- 不要使用一个钱包签署大量并发存储操作。 并发交易会争用同一批自有 Gas 和存储对象。发布器通过内部子钱包处理此问题;如果你要构建自己的上传器,也应采用这种方式。
- 共享钱包时,请关闭
reuse_resources。 启用重用会导致两个正在进行的上传争用同一批对象,并可能造成 Blob 已注册但从未认证。 - 确保资金钱包余额充足。 监控主钱包中的 SUI 和 WAL;发布器会从主钱包为其子钱包补充资金。
字节范围和流媒体
聚合器支持 HTTP Range 标头,并返回 206 Partial Content,从而允许浏览器在视频中定位播放。也可以使用查询参数形式:
curl -H "Range: bytes=0-999" "$AGGREGATOR/v1/blobs/<BLOB_ID>"
curl "$AGGREGATOR/v1/blobs/<BLOB_ID>/byte-range?start=0&length=1024"
<video> 或 <audio> 元素可以将聚合器 URL 用作其 src。按 Blob ID 读取时不会返回内容类型,且聚合器会有意阻止类型嗅探,因此请在 Blob 上设置 content-type 属性,并按对象 ID(/v1/blobs/by-object-id/<OBJECT_ID>)读取,以便返回标头,让浏览器播放内容而不是下载。字节范围读取只会验证获取到的字节,不会验证整个 Blob。
查询系统信息### 查询系统信息
# Get current epoch, storage cost, and network parameters
curl "$AGGREGATOR/v1/info"
返回 epoch 编号、epoch 时长和系统参数。可用于计算成本,并在存储请求中设置 epochs 之前检查当前 epoch。
规则
- Mainnet 上没有公共 Publisher。 在 Mainnet 上,请运行自己的经过身份验证的 Publisher,或使用 TypeScript SDK/上传中继。公共端点仅适用于 Testnet。
- 新 Blob 默认可删除。 如果需要保证可用性,请明确设置
permanent=true。 - 立即上传后重试读取。 CDN 前置的聚合器可能会短暂缓存 Blob 传播前的 404。请采用退避策略重试。
- 读取内容时使用 Blob ID,读取属性时使用对象 ID。 使用对象 ID 读取会返回 Blob 属性中的自定义 HTTP 标头。使用 Blob ID 读取则不会。
- 检查响应类型。 存储响应为
newlyCreated或alreadyCertified。两种情况都表示成功。
常见错误
- 以为 Mainnet 上有公共 Publisher。 实际上没有。你必须运行自己的 Publisher、使用上传中继,或直接使用 TypeScript SDK。
https://upload-relay.mainnet.walrus.space上的上传中继是最简单的 Mainnet 写入途径。 - 未检查响应中的
alreadyCertified。 当相同内容已有足够的有效期时,Publisher 会返回此状态。这不是错误。 - 存储后立即读取,却收到 404。 CDN 缓存可能会导致短暂的 404。请采用退避策略重试。
- 省略
epochs,导致仅存储 1 个 epoch。 默认值为 1 个 epoch。请务必明确设置epochs。 - 混淆 Publisher 和 Aggregator 的作用。 Publisher 负责存储(PUT),Aggregator 负责读取(GET)。它们是 URL 不同的独立服务。
- 将
503 BLOB_UNAVAILABLE视为永久性错误。 从 v1.47 起,如果 Blob 只是暂时无法读取,Aggregator 会返回可重试的503,而不是500。请采用退避策略重试。 - 期待读取 Blob ID 时获得内容类型。 只有通过对象 ID 读取才会返回
content-type等属性标头。 - 在 Publisher 上遇到
413 Payload Too Large。 某些 Publisher 会限制上传大小(例如,公共 Testnet Publisher 限制为 10 MiB)。对于大型文件,请使用 CLI、TypeScript SDK,或运行自己的 Publisher。 - 不明白为什么微小 Blob 的
storageSize约为 66 MB。 无论 Blob 大小如何,Walrus 都会为每个 Blob 增加约 64 MB 的固定元数据开销。对于小于约 10 MB 的 Blob,元数据成本占主导。大量小型 Blob 请使用 quilts。 - 使用过时的 Aggregator URL。
aggregator.walrus.site和aggregator.devnet.walrus.space已过时。Mainnet 请使用aggregator.walrus-mainnet.walrus.space,Testnet 请使用aggregator.walrus-testnet.walrus.space。