基础地址与限制
基础地址是 https://scan.rbrc20.xyz,所有响应都是 JSON。不需要密钥,也不需要注册:读取完全开放,唯一的写入接口只接受交易哈希,并在相信任何内容之前先到链上核实。你无法通过请求把虚假内容写进索引,只能让它去查看链上真实存在的东西。
- 铭文大小
- 8,192 字节
- 收录前的区块确认数
- 3 个区块
- 上报时限
- 10 分钟
- 上报频率
- 每个 IP 每分钟 20 次
- 列表每页
- 最多 200 行
写入流程
索引器不扫描区块。一条铭文要通过上报才会被收录:你自己在链上写入,等待 3 个区块,然后提交交易哈希。服务器会从链上读取这笔交易,记录链上的实际内容,而不是你声称的内容。所以无论从哪个网站或脚本写入,流程都是三步:
- 生成 calldata:使用
/encode,或者自己把data:URI 编码为十六进制。 - 用你自己的钱包签名,把它作为一笔发给你自己地址、金额为 0 的交易发出。这个服务从不签名,也从不接触私钥。
- 等待 3 个区块,并在交易所在区块的时间之后 10 分钟内,用哈希调用
POST /writings。
10 分钟规则
一条铭文只有在写入后 10 分钟内上报才会被计入。时间从它所在区块的时间戳开始计算,与服务器核验上报时的时钟比较。超过时限的上报会被永久拒绝。
原因是规则按链上顺序重放铭文。如果没有时限,一条被扣留、事后才上报的铭文会被重放到之后写入的所有内容前面。卖家可以先写入一笔转账但暂不上报,再挂单出售同一批代币,收到付款后再上报那笔转账,让买家的购买无法转移任何代币。用同样方式扣留的更早的部署,也可以抢走别人已经在铸造的代号。任一时刻过去 10 分钟后,就不会再有更早的铭文被加入,那一时刻之前的记录便已确定。
在这条规则出现之前收录的铭文没有保存区块时间,它们的 "blockTime" 为 null,视为已确定。
GET /encode
把文字转换为钱包可以签名的交易字段。不是 data: URI 的内容会被包装成 URI。
curl "https://scan.rbrc20.xyz/encode?text=hello%20chain"
{
"value": "0x0",
"data": "0x646174613a2c68656c6c6f20636861696e",
"text": "data:,hello chain",
"bytes": 17,
"note": "send this to your own address with value 0. this service never signs."
}
响应中特意没有 to:铭文是发给你自己的交易,所以由你自己填写地址。如果服务指定一个地址,就给了错误地址混进来的机会。
POST /writings
上报一条已经在链上的铭文。请求体只有一个哈希。已经收录的哈希会立即返回 "already": true,即使已经过了 10 分钟,所以重复上报总是安全的。
curl -X POST "https://scan.rbrc20.xyz/writings" \
-H "content-type: application/json" \
-d '{"hash":"0xdf88b6091854894f716e8ce7e88e230b14fb971e369c57ed2b1fdb0404393b03"}'
{
"recorded": true,
"already": true,
"writing": {
"txHash": "0xdf88b6091854894f716e8ce7e88e230b14fb971e369c57ed2b1fdb0404393b03",
"block": 51544509, "txIndex": 5,
"from": "0x8648…1cc5", "to": "0x8648…1cc5",
"media": "text/plain", "protocol": "rbrc",
"body": "{\"p\":\"rbrc\",\"op\":\"deploy\",\"tick\":\"hood\",\"max\":\"21000000\",\"lim\":\"1000\"}",
"bytes": 70, "value": "0", "blockTime": null
}
}
这是一条真实收录的铭文,即 hood 的部署。它在保存区块时间之前就已收录,所以 blockTime 为 null。
body 是 data: URI 逗号之后的内容,不含 data:, 前缀,bytes 只计算这部分的字节数。media 是 URI 头部的媒体类型,头部为空时视为 text/plain。
首次上报的响应格式相同,只是没有 already。拒绝时返回 422 和一段文字原因,原因只有以下几种:找不到该哈希的交易、尚未打包进区块、区块太新(稍后重试)、交易在链上执行失败、不是发给自己地址的交易、附带了金额、没有 data: URI、超过 8,192 字节、包含控制字符、上报太晚,或者无法读取区块时间(稍后重试)。唯一的格式例外是购买:购买要付款给卖家,所以购买铭文必须发给另一个地址,并且必须附带金额。
上报太晚时的拒绝原文如下(原因文字为英文):
{ "error": "that inscription was written more than ten minutes ago. an inscription counts only if it is reported within ten minutes of being written" }
"that transaction is not in a block yet"(交易尚未打包进区块)、"that block is too new"(区块太新)和 "could not read when that block was made"(无法读取区块时间)值得重试;发送后最初几秒内,索引器的节点还没看到交易时出现的 "no transaction with that hash"(找不到交易)也一样。无法读取区块时间是读取链失败,不是对交易的判定,所以请在 10 分钟内尽早重试。其他拒绝,包括上报太晚,无论重试多少次都不会改变。
GET /writings
所有人写入的全部内容,按从新到旧排列。可以用 address 或 protocol 筛选,用 limit(默认 50,最多 200)和上一页 next 字段中的 before 游标翻页。
curl "https://scan.rbrc20.xyz/writings?protocol=rbrc&limit=2"
{
"count": 2,
"next": "61900398.0",
"writings": [ { "txHash": "0x…", "block": 61900412, "txIndex": 1, "from": "0x…",
"protocol": "rbrc", "body": "{\"p\":\"rbrc\",\"op\":\"mint\",…}",
"blockTime": 1789312345, … }, … ]
}
要从头重放,请使用 order=asc,并用 after 游标向后翻页。每一页包含游标之后的行,从旧到新排列,next 仍是本页最后一行的游标。
curl "https://scan.rbrc20.xyz/writings?protocol=rbrc&order=asc&limit=200" curl "https://scan.rbrc20.xyz/writings?protocol=rbrc&order=asc&limit=200&after=51544509.3"
按哈希读取单条铭文:GET /writing/0x…。游标是 block.txIndex 而不是偏移量,所以即使新铭文不断写入,翻页也不会跳过或重复。
GET /tokens
rbrc 协议标识下部署的全部代号。sort=hot(铸造最多,默认)或 sort=new。传入 wallet=0x… 时,每一行还会带上 yourMints 和 mintsAllowed,这样铸造按钮在显示之前就能知道是否可以点击。
curl "https://scan.rbrc20.xyz/tokens?sort=hot"
{
"count": 1, "reportWindowSeconds": 600, "now": 1789312900,
"tokens": [ {
"tick": "name", "max": "21000000", "lim": "1000",
"minted": "15000", "percent": 0.07, "soldOut": false,
"mints": 15, "holders": 3,
"deployer": "0x…", "block": 61900001, "txHash": "0x…",
"blockTime": 1789312300, "mintableAt": 1789312900, "settling": false
} ]
}
blockTime 是部署所在区块的时间,mintableAt 是它加上上报时限,settling 只在 now 早于 mintableAt 时为 true。对于保存区块时间之前收录的部署,这两个字段为 null,settling 为 false。代币处于等待期时,这个网站不会提供铸造:同一代号更早的部署仍可能被上报,那时现在写入的铸造就会属于那个部署。
GET /token/:tick
单个代号,字段相同,只有 holders 不同:这里是前 100 名持有人的列表,而不是 /tokens 给出的数量。没有部署过的代号返回 404 和 {"error": "no such ticker"}。中文代号放进路径时按 UTF-8 百分号编码一次:/token/%E9%BE%99。
curl "https://scan.rbrc20.xyz/token/name"
{
"tick": "name", "max": "21000000", "lim": "1000", "minted": "15000",
"percent": 0.07, "soldOut": false, "mints": 15,
"deployer": "0x…", "block": 61900001, "txHash": "0x…",
"blockTime": 1789312300, "mintableAt": 1789312900, "settling": false,
"holders": [ { "address": "0x…", "amount": "5000" }, … ]
}
GET /market
在售挂单,按代号分组,每组按单价从低到高排列,并带有该组的地板价。?tick=name 只看一个代号;?flat=1 返回一个不分组的 listings 列表。
curl "https://scan.rbrc20.xyz/market?tick=name"
{
"tickers": 1, "listings": 3, "reportWindowSeconds": 600, "now": 1789312900,
"groups": [ {
"tick": "name", "floor": "1800000000000", "listings": 3, "forSale": "4000",
"minted": "15000", "holders": 3,
"rows": [ { "id": "0x…", "amt": "1000", "price": "1800000000000000",
"unit": "1800000000000", "seller": "0x…", "block": 61900012,
"blockTime": 1789312500, "buyableAt": 1789313100, "settling": true }, … ]
} ]
}
价格单位是 wei。id 是挂单铭文的交易哈希,购买时就是指明这个 id。buyableAt 和 settling 的含义与代币字段相同:挂单处于等待期时,卖家仍可能上报一笔在挂单之前写入、会清空其余额的转账,所以在 buyableAt 之前这个网站不会提供购买。
GET /balances/:addr
一个地址在所有代号上的持有情况,包括已用于在售挂单的数量,以及已使用的铸造次数。
curl "https://scan.rbrc20.xyz/balances/0xyouraddress"
{
"address": "0xyouraddress",
"balances": [ { "tick": "name", "amount": "5000", "listed": "1000", "free": "4000",
"lim": "1000", "max": "21000000", "mintsUsed": 5, "mintsAllowed": 20 } ]
}
GET /activity
事件动态,从新到旧:规则接受的每一次部署、铸造、转账、挂单、取消挂单和购买。可以用 tick 或 address 筛选,用 limit(最多 200)限制数量。
curl "https://scan.rbrc20.xyz/activity?tick=name&limit=1"
{
"events": [ { "kind": "buy", "tick": "name", "who": "0x…", "seller": "0x…",
"amt": "1000", "price": "1800000000000000", "block": 61900031, "txHash": "0x…" } ]
}
GET /health
索引器能否访问链,以及已经收录了多少内容。
curl "https://scan.rbrc20.xyz/health"
{
"ok": true, "protocol": "rbrc", "head": 61900950, "rpcOk": true,
"writings": 74, "lastWritingBlock": 61900412,
"reportWindowSeconds": 600, "rulesV1Block": 61834151, "rulesV2Block": null
}
无法读取链的最新区块时,ok 为 false。这期间新的上报无法核验,铭文的上报时限可能因此耗尽;已收录内容的读取不受影响。rulesV2Block 是规则 v2 开始生效的区块,v2 未启用时为 null,目前生产环境就是这样。早于 v2 的索引器不返回这个字段,同样按 null 处理。
操作
代币规则由读取者执行,不在合约里。一个操作是 data: URI 中的紧凑 JSON 对象,协议标识为 rbrc,作为发给自己地址、金额为 0 的交易写入。购买除外,它写在付款交易本身上。数量都是字符串。
deploy data:,{"p":"rbrc","op":"deploy","tick":"name","max":"21000000","lim":"1000"}
mint data:,{"p":"rbrc","op":"mint","tick":"name","amt":"1000"}
transfer data:,{"p":"rbrc","op":"transfer","tick":"name","amt":"1000","to":"0x…"}
list data:,{"p":"rbrc","op":"list","tick":"name","amt":"1000","price":"1800000000000000"}
cancel data:,{"p":"rbrc","op":"cancel","id":"0x…listing tx hash…"}
buy data:,{"p":"rbrc","op":"buy","id":"0x…listing tx hash…"} (sent to the seller, value >= price)
一条铭文要被计入必须满足的全部规则:代号为 1 到 16 个 a-z、0-9 和 - 字符(自区块 61,834,151 起,先把 ASCII 字母 A-Z 转为小写,其他字符不做任何改变),使用不符合这一格式的代号的铭文会被忽略。规则 v2 启用后会增加中文代号,见下文。同一代号只有第一次部署有效,之后的部署都会被忽略。铸造数量必须正好等于 lim,超过 max 会被拒绝,每个钱包每个代号最多铸造 20 次。转账和挂单只能以完整的铸造单位进行,并且只能使用未用于在售挂单的余额。取消挂单必须由卖家发出。取消后挂单立即下架,但自规则 v1 起,数量在取消后仍锁定 10 分钟(规则 v2 起为 20 分钟),这段时间内打包的购买仍会成交,因为发出购买的人还看不到取消。购买只有在付款确实发给了卖家、并且确实足额时才会计入,这两点都从链上读取,所以任何人都无法靠请求拿走代币。
规则 v1,自区块 61,834,151 起
区块 61,834,151 及之后写入的铭文还需满足以下规则。该区块之前写入的铭文按原来的方式读取,所以已有的余额都不会改变。
- 代号中的 ASCII 字母
A-Z会在检查之前转为小写,所以用大写写入的代号和用小写写入的是同一个代号。其他字符都不改变:Unicode 小写转换会把开尔文符号变成k,索引器不会这样做。 - 所有数量(
max、lim、amt、price)都必须是规范的正整数:只有数字,不以 0 开头,不为 0,最多 30 位。 - 部署要求
lim不大于max,并且max能被lim整除,这样总量总能铸造到最后一个单位。 - 挂单价格必须大于 0。
- 读取购买时,协议标识不区分大小写。
- 取消挂单后,挂单的数量在取消所在区块之后仍锁定 10 分钟,这段时间内打包的购买仍会成交。
违反规则的铭文不会在任何地方报错:它会作为铭文被收录,只是不会改变任何余额。
规则 v2:中文代号
规则 v2 已经写好,但处于关闭状态。它从 /health 中 rulesV2Block 指定的区块开始生效,目前生产环境中该值为 null,所以下面的内容暂不计入。这个区块会在产出之前确定,确定之后不再改变。该区块之前写入的铭文永远保持 v1 的含义:之前写入的中文部署会被忽略,也不会占用代号。
- 代号要么是 v1 的 ASCII 形式,要么是 1 到 8 个字符、每个字符都在
U+4E00到U+9FA5之间,即 Unicode 1.1 的 CJK 统一汉字基本区。其他字符都不允许,两种形式也不能混用。 - 中文形式按原样使用:不去除空格,不转换大小写,不做 Unicode 规范化,也不合并异体字或形近字。对任何代号的唯一改变,就是 ASCII 字母
A-Z转为小写。 - 只有字符的码位完全相同,两个代号才是同一个。简体和繁体,例如“
龙”和“龍”,是两个不同的代号,各自以第一次部署为准。 - 代号在 JSON 解析之后读取,所以
"\u9f99"和"龙"是同一个代号。请直接写入汉字本身。 - 数量、部署限制、挂单价格、上报时限和每个钱包的铸造上限都不变。唯一的变化是取消挂单:自 v2 起,取消后数量锁定 20 分钟(两个上报时限),这段时间内打包的购买仍会成交。
只有当索引器的 head 达到 rulesV2Block 之后,这个网站才会提供中文代号的部署或铸造;当一个代号与已部署的代号只有简繁或形近字差别时,页面会给出提示。这个提示只是建议,规则不会依据它做任何判断。
同一挂单的两笔购买
一个挂单只能被购买一次。如果同一个挂单有两笔购买上链,后一笔付款仍会到达卖家,因为它是普通的 ETH 转账,任何规则都无法阻止,但它不会转移任何代币。在取消挂单的锁定期结束后才上链的购买也是如此(锁定期为 10 分钟,规则 v2 起为 20 分钟)。没有退款机制。所以请在付款前确认挂单仍然有效,也不要购买可能有别人同时在买的挂单。
购买上链后的 10 分钟内仍可能失效。“第一笔”按链上顺序计算,而不是按上报到达的顺序,所以同一挂单一笔更早但尚未上报的购买,可以在它自己的 10 分钟内被上报并拿到挂单。这时你的购买不会转移任何代币,你的 ETH 已经转给卖家,不会退款。
核查索引
每条收录的铭文都注明了它的交易,所以每一条都可以在链上核查:发送方、接收方、金额和完整的 calldata 都可以对比。GET /writings?order=asc 按链上顺序提供全部收录内容,任何人都可以在上面重新执行规则,看是否得到与这个 API 相同的数字。
仅凭链本身无法知道哪些铭文是在时限内上报的。这份列表是索引器的记录,所以每一行都保留了交易和区块时间,让你需要信任的部分尽可能少,也尽可能可以核查。