跳到主要内容

您正在浏览 Arc Testnet(链 5042002)。这里的代币没有价值。

USDC 价格:$1.0000Gas:
Arcscan

REST API

Arcscan 通过一套 HTTP API 读取 Arc,而这套 API 无需密钥、无需账户即可从外部访问——本页上的每一条路径都是先经公网真实调用过,才被写下来的。

基础 URL#

API 有自己的主机名,每条链一个:api.arc-scan.io 对应 Arc 主网,链 ID 5042;api-testnet.arc-scan.io 对应 Arc 测试网,链 ID 5042002。请以它们为开发对象:

https://api.arc-scan.io/v1          # Arc mainnet, chain 5042
https://api-testnet.arc-scan.io/v1  # Arc Testnet, chain 5042002

两个主机提供同样的两套接口:/v1/… 是类型化的 REST API,一个资源一条路径,返回的正是本浏览器自身用来渲染页面的文档;/api?module=…&action=… 则是大家熟悉的兼容契约,现成的工具已经会说这门话。两个主机之间的差别只在于各自回答哪条链,所以把客户端切到测试网就只是换一个主机名,别的都不用动。

本站自己的 /_api 路径并不是 API

你可能会注意到,浏览器页面是从本站自己的源站去取 /_api/v1/… 的,而且你手动调用它也确实有响应。那是网站通往同一个服务的内部改写路由,是留给它自己的页面用的:它不返回任何 CORS 头,带着 noindex 头下发,并且可能因为与你毫无关系的原因被改掉。请以上面的主机名为准,并把主机名固定在一个常量里,这样你只需要改一处。

可以从浏览器调用——但只限这两个主机

API 主机允许跨源调用:Access-Control-Allow-Origin: *,预检中允许 Content-TypeX-Api-KeyIf-None-Match,并向调用方开放 ETagX-Request-Id 以及限流相关的响应头。而本站自己的 /_api 路径完全不带 Access-Control- 头,所以指向它的 fetch() 在浏览器里会失败,同样一条请求用 curl 却能成功——错误的地址正是这样才一直没被发现。

两套接口#

同一个节点和同一份索引,通过两种不同的形态作答。类型化 API 正是这个浏览器渲染所依据的,因此页面上可见的任何内容都能以同样的形式读成 JSON。兼容 API 复现了钱包、部署脚本和索引器已经在说的那套事实标准浏览器 REST 契约,因此现有工具只要改一个基础 URL 就能指向 Arc。

接口形态成功信封
/v1/…类型化 REST,每种资源一条路径文档本身,snake_case 键名
/api?module=…&action=…一条路径,按查询字符串分发{"status":"1","message":"OK","result":…}

端点#

下面每一条路径在写这一页时都对主网真实调用过。它们全都作了回答;其中两条回答 501,而这两条都被写在了它们各自所属的位置,而不是被省略——一次有文档记载的拒绝,比一处空白更有价值。

链、首页与链头#

/v1/chain 是第一个该调用的:它给出链 ID、原生货币及其小数位数、本部署具备哪些能力,以及这条链究竟被索引了多少。请读取它,而不要把这些内容写死——两条链并不相同,而数据覆盖范围解释了其中的索引部分告诉你什么。

curl https://api.arc-scan.io/v1/chain

# {"chain_id":5042,"name":"Arc","is_testnet":false,
#  "native":{"symbol":"USDC","decimals":18},
#  "block_time_ms":506,"finality":"instant",
#  "capabilities":{"trace":true,"archive":true,"debug":false,…},
#  "index":{"available":true,"complete":true,…}}
路径它回答什么
GET /v1/chain链常量、能力与索引覆盖范围
GET /v1/home最新区块与交易,合在一份文档里
GET /v1/stats/summary首页显示的那些头条计数器
GET /v1/stats/gas费用追踪器:当前和近期的 Gas 价格
GET /v1/stream/head服务器推送事件,每个新区块一帧

/v1/stream/head 是一个 SSE 流,不是 JSON 文档——它保持连接打开,大约每秒推送两帧。每一帧都带有 server_now,因此客户端不必信任自己的时钟就能算出诚实的数据年龄。

curl -N https://api.arc-scan.io/v1/stream/head

# event: head
# data: {"height": 14852424, "hash": "0x68ce06…f3775", "timestamp": 1786360005,
#        "tx_count": 0, "server_now": 1786360007, "available": true}

区块#

区块引用可以是高度、哈希,或者字面量 latest。列表接受 limit 和一个不透明的 cursor;各字段的含义见区块

curl "https://api.arc-scan.io/v1/blocks?limit=2"
curl  https://api.arc-scan.io/v1/blocks/latest
curl  https://api.arc-scan.io/v1/blocks/14852000
curl "https://api.arc-scan.io/v1/blocks/14852000/txs?limit=10"

交易#

交易按哈希寻址。调用树在主网上可用,因为那里的 trace 为 true;状态差异不可用,因为 debug 为 false,而它会以 501 说明这一点,而不是给出一个空回答。

H=0x128cb07da24289341bcc57e3129ef78f82b5a1769c30156774487fe9e98251e9

curl "https://api.arc-scan.io/v1/txs?limit=5"
curl "https://api.arc-scan.io/v1/txs/$H"
curl "https://api.arc-scan.io/v1/txs/$H/raw"
curl "https://api.arc-scan.io/v1/txs/$H/trace"

curl "https://api.arc-scan.io/v1/txs/$H/state"
# 501 {"error":{"code":"CAPABILITY_UNAVAILABLE",…}}  — no debug namespace on mainnet

地址与代币#

A=0xf40dc55b06e4e8c042430ecf1995d0ec6b9ae033
T=0x3600000000000000000000000000000000000000   # the native currency as an ERC-20

curl "https://api.arc-scan.io/v1/address/$A"
curl "https://api.arc-scan.io/v1/address/$A/txs?limit=10"
curl "https://api.arc-scan.io/v1/address/$A/activity?limit=10"
curl "https://api.arc-scan.io/v1/address/$A/logs?limit=10"
curl "https://api.arc-scan.io/v1/address/$A/tokens"

curl "https://api.arc-scan.io/v1/tokens/$T"
curl "https://api.arc-scan.io/v1/tokens/$T/info"

持有者在主网上有索引,因此 /v1/tokens/{address}/holders 对普通代币会作答。它对 0x3600…0000 处的原生货币予以拒绝,消息里解释了原因:那些余额就是账户余额,索引两遍会把每个账户重复计算一次。

搜索、图表与解码#

搜索解析的内容与浏览器自己的搜索框相同——高度、哈希、地址。图表索引列出每个指标及其 id,而 /v1/charts/{metric} 返回那一条序列;tx 就是其中之一。解码是本页上唯一的 POST,而且完全不需要查询链。

curl "https://api.arc-scan.io/v1/search?q=0x3600000000000000000000000000000000000000"
curl "https://api.arc-scan.io/v1/search/suggest?q=0x36"
curl  https://api.arc-scan.io/v1/charts
curl  https://api.arc-scan.io/v1/charts/tx

curl -X POST https://api.arc-scan.io/v1/decode \
  -H 'content-type: application/json' \
  -d '{"input":"0xa9059cbb…"}'

# {"selector":"0xa9059cbb","decoded":{"name":"transfer",
#  "signature":"transfer(address,uint256)","args":[…]},"error":null}

兼容接口#

/api?module=…&action=… 说的是大家熟悉的那套浏览器契约:一条路径、一个 module 和一个 actionresult 中的每个标量都是字符串。proxy 模块会把 JSON-RPC 读取透传出去,并以 JSON-RPC 的形态而不是状态信封作答。

curl "https://api.arc-scan.io/api?module=proxy&action=eth_blockNumber"
# {"jsonrpc":"2.0","id":1,"result":"0xe2a12f"}

curl "https://api.arc-scan.io/api?module=account&action=balance&address=0xf40dc55b06e4e8c042430ecf1995d0ec6b9ae033"
# {"status":"1","message":"OK","result":"20456053552414099311"}

curl "https://api.arc-scan.io/api?module=stats&action=ethsupply"

那套契约的动作并非在这里全部存在——凡是需要 Arc 所没有的数据、或者需要我们并未保留的索引的动作,都会被按名拒绝。站内的 API 参考在新标签页中打开列出了完整的分发表以及哪些动作不可用;它由服务本身生成,因此不会像本页这样发生偏离。

如何读这些 JSON#

有四条约定造成了所有值得一提的集成缺陷。第一条代价最高:18 位小数的金额在 JavaScript 的 Number 中无法保全,因此金额以字符串跨越网络传输,也必须按字符串解析。

约定它在传输层上意味着什么
金额是一个对象,不是一个数字:raw(整数字符串)、decimalsformatted(精确值)、usdsymbol。Gas 数值和供应量同样是十进制字符串。区块高度是 JSON 数字。
大小写键名是 snake_case。地址和哈希是小写,其显示形式放在旁边的 checksum 字段里。输入时任何大小写都接受。
时间Unix 秒,绝不预先格式化。区块大约每秒到达两个,而时间戳只精确到秒,因此它们不构成全序——切勿按它们排序或分页。
分页page.next 下的不透明游标,不是页码。page.has_more 告诉你是否要继续。

已提交的历史是不可变的,缓存方式也照此对待

以已提交高度或已上链哈希为键的响应,会以 Cache-Control: public, max-age=31536000, immutable 提供。Arc 具有即时最终性且没有重组,因此这是一个真实的保证而不是概率性的:把那些响应永久缓存起来,然后完全跳过请求。

错误#

一次拒绝是一个 JSON 对象,包含一个机器可读的 code、一条写给人看的消息,以及一个可选的 detail。请按 code 分支,绝不要按消息文本。

curl https://api.arc-scan.io/v1/blocks/999999999999
# 404
# {"error":{"code":"NOT_FOUND","message":"No block at height 999999999999","detail":null}}

curl https://api.arc-scan.io/v1/tokens/0x3600000000000000000000000000000000000000/holders
# 501
# {"error":{"code":"CAPABILITY_UNAVAILABLE",
#   "message":"The native gas token has no separate holder list: its balances are account
#              balances, and indexing them again would double-count every account.",
#   "detail":{"capability":"holder_index","detail_key":"holdersNativeToken"}}}
状态码code何时出现
404NOT_FOUND没有这样的区块、交易、地址记录或代币。
429RATE_LIMITED请求过多。附带以秒为单位的 Retry-After
501CAPABILITY_UNAVAILABLE该数据需要一项本链或本部署并不具备的能力。
502UPSTREAM_ERROR节点作了回答,但没有回答出有用的内容。
503INDEX_OVERLOADED一个重查询被丢弃,而不是排队。
504UPSTREAM_TIMEOUT节点没有及时回答。

读错误信封,而不只是状态码

格式错误或超出范围的参数——无法解析的区块引用、超过上限的 limit、缺少的必需查询、拼错的 JSON 字段名——会以 400 {"error":{"code":"INVALID_INPUT","message":"limit: Input should be greater than or equal to 1","detail":null}} 返回。code 指出错误的类别,message 指出引发错误的字段,这通常比重读 URL 更快。这里的 404 表示该资源确实不存在。

限制与访问#

没有 API 密钥、没有等级,也没有什么需要注册。请求按调用方以令牌桶计量,每一个响应都会告诉你当前的处境——请读取响应头,而不要把某个数字写死,因为这个预算是一项运维设置,不是一个公开承诺。

响应头含义
X-RateLimit-Limit该请求所计量的那个桶的容量。
X-RateLimit-Remaining桶中剩余的令牌数。
Retry-After仅在 429 或 503 时出现:重试前需要等待的整秒数。
X-Request-Id出现在 API 响应上。如果你需要就某个请求询问我们,请引用它。

另有两个上限是真实存在的,而且会被明确报告而不是隐藏。日志查询被限制在一个最大区块跨度内,超范围的请求会被拒绝,并在消息中写明那个最大值,而不是被无声地截断。Trace 和状态差异调用运行在一个专用小池上,带有实际耗时预算和大小上限,并会设置 truncated: true,而不是一直挂着。

不通过我们的索引读取 Arc

如果你想要的是这条链本身而不是我们对它的视图,我们还为主网运行一个公共只读 JSON-RPC 端点——见公共 RPC。另外还有一份纯文本的 /llms.txt在新标签页中打开,描述这个浏览器持有什么,供那些先读散文再读 schema 的程序使用。
REST API · Arcscan 文档 | Arcscan