面向开发者 / 应用 API

浏览器 API

节点刻意不去当的那个归档。它保存完整的历史,它是这条链上唯一带调用轨迹的表面,而且它在最强的意义上是只读的:每一个 POST 都是 405。

它为什么存在

节点保留一个很短的历史窗口,大约两分钟的区块,而窗口之外的查询回答 null 而不是 一个错误。那是一个刻意的取舍:它快速地服务当下,并把过去交给一个为此而建的东西。这个服务就是 那个东西。排序器一边走一边把每一条日志复制进 Postgres,而这个 API 读的就是那份索引。

所以有两个问题只在这里、而不在别处得到回答:

  • 任何比节点窗口更老的东西。今天早上的一笔交易、上周的一个区块、一个代币 的完整转账历史。
  • 调用轨迹。节点根本不暴露 debug 命名空间,所以 GET /tx/{hash} 是这条链上唯一能看到一笔交易内部调用的地方。
它是一份索引,不是第二个节点

某些路由上的某些字段是在请求被处理时从节点实时读来的:一个余额、一条域名服务记录、一次 合约探测、一个索引还没追上的区块的迷你区块。当节点连不上时,那些字段回来是 null 或者缺席, 而答案的其余部分仍由索引提供,所以一个部分答案是正常的,而且不会抛出错误。

基础 URL 与 CORS

接入点Value
公开https://explorer.picklechain.xyz/api/域名服务站点和工具箱站点也在 /api/ 下挂载了它
你自己运行的一套栈http://127.0.0.1:4010这个服务自己的端口;在随附的 compose 文件里它没有被发布到容器网络之外
CORS一份允许名单OPTIONS 回答 204 并允许 GET 和 OPTIONS;不在名单上的 Origin 被以 403 拒绝

链

区块、迷你区块、交易,以及费用分成。

Params
none
返回
a flat object of counters

Chain-wide counters: block and transaction totals, wallets, gas used, the cadence figures the node reports, the mini-block head, index lag and the spool's own health.

另见路径。 GET /

值得注意。 Recomputed once a second by a background thread and served from a cache for six tenths of a second, so two calls in the same instant give the same answer. It also carries a rate counter this reference does not quote: the site publishes no throughput figure, and the number is local anyway.

Params
none
返回
{stats, charts, blocks, txs, topAccounts}

The explorer's front page in one call: the cached stats, 48 chart points, the 8 most recent blocks that carried transactions, 12 transactions and the 8 busiest accounts.

值得注意。 Use this instead of five calls. Its parts are the other routes' defaults and nothing about it is configurable.

Params
limit (default 48, clamped to 200)
返回
[{number, timestamp, txCount, gasUsed}]

A bare array, oldest first.

值得注意。 It prefers blocks that carried transactions and falls back to all blocks only when fewer than four match, so the series is not evenly spaced in time and must not be read as one.

Params
limit, offset, active=1
返回
[{number, hash, timestamp, gasUsed, txCount, miniCount}]

A bare array, newest first. `active=1` returns only blocks that carried transactions.

值得注意。 No total is returned, so there is nothing to page against except asking until you get a short answer.

Params
limit, offset over the block's transactions
返回
one block with its transactions and mini-blocks

The number is parsed permissively: decimal and 0x both work.

值得注意。 `limit` defaults to 50 here rather than 25, and the mini-blocks fall back to a live read against the node when the index has none for the block. 404 when unknown.

Params
limit, offset
返回
{total, minis: [...]}

Mini-blocks, newest first. One of the few routes that does return a total.

值得注意。 Timestamps are `timestamp_us`: MICROSECONDS, not seconds, and a decimal number rather than a hex quantity.

Params
limit, offset over the transactions
返回
one mini-block

By decimal number or by hash.

值得注意。 When the index does not have it, the service asks the node - and the answer then ALSO carries `stateDiffHash`, `sequencerSig` and `receipts`, which the indexed answer does not. The shape depends on where it was found.

/txs

GET
Params
limit, offset
返回
a bare array, newest first

Transaction summaries.

值得注意。 No total.

Params
none
返回
the full transaction

The richest object in the API: input data, the decoded method for known selectors, logs with labelled addresses, CALL TRACES, token transfers and NFT transfers.

值得注意。 The traces are the reason this route exists. The node exposes no debug namespace at all, so there is nowhere else on this chain to get them. 404 when unknown.

Params
none
返回
{deployed, router, split, burn, launches, arcadeSkims, deferred, claimed, pendingEthWei, ...}

Everything the fee split has done and everything still waiting, read from the log spool rather than over RPC.

值得注意。 `{"deployed": false}` and NOTHING ELSE when the fee layer is not in the manifest - that is an ordinary state, not an error, because that layer is deployed by hand. The ether side and the token side are kept as separate figures and never summed.

账户

谁做过交易,以及关于某一个地址的一切已知信息。

Params
limit, offset
返回
{total, accounts: [...]}

Accounts ordered by how much they have transacted.

值得注意。 The ordering is by transaction count, not by balance.

Params
limit, offset over the transaction lists
返回
the largest payload in the service

Balance, nonce, counts, whether it is a contract, its creator and what it created, token and NFT holdings with metadata, the name-service record, and recent transactions and transfers.

值得注意。 `bytecode` is TRUNCATED to 400 hex characters with an ellipsis appended; `bytecodeSize` is the real length. The whole answer is cached for a few seconds under a key that includes the paging, so two different pages are two different cache entries.

代币、NFT 与域名

与注册表合并过的元数据,以及那条唯一不是 JSON 的路由。

Params
none
返回
a list of at most 40 tokens

PKL pinned first, then by transfer count. Each entry merges a live probe of the contract with the operator's registry entry.

值得注意。 Forty is a hard cap and there is no paging past it. An address that probes as an NFT is skipped even if the registry calls it a token.

Params
none
返回
{nfts: [...]}

At most 40 collections, verified ones first, then by how many have been minted.

值得注意。 The collection list is DISCOVERED from transfer logs rather than registered, so a collection nobody has traded is absent.

Params
limit, clamped to 48
返回
the collection, its items and its 30 most recent transfers

Collection metadata merged from the chain and the registry.

值得注意。 Items are fetched one at a time up to the clamp, and off-chain metadata is resolved by a BACKGROUND thread - so the first request for a cold collection returns items whose metadata is still missing, and a second request a moment later returns more. Held for fifteen seconds in a cache of its own.

Params
none
返回
one item plus `collectionMeta`

One token of a collection.

值得注意。 The token id must be all digits, or the path does not match this route at all and you get the 404 for an unknown route.

Params
none
返回
{name, label, available, reserved, owner, resolved, expires, price, twitter, website, description}

A name-service lookup, read live from the registry contract.

值得注意。 A trailing suffix is stripped, and the label must be 3 to 32 characters. A name outside that range, and any lookup at all when the name service is not configured, is a 404 - which is indistinguishable from a name that does not exist.

Params
none
返回
raw image bytes

The only non-JSON, non-stream route. The content type is inferred from the stored file's extension.

值得注意。 404 as JSON when there is no logo, so a client must check the status before treating the body as an image.

实时,以及两个非 GET 动词

事件流、预检,以及那个 405。

Params
none
返回
text/event-stream, one stats frame per update

Server-sent events carrying the same object /stats returns, pushed when it changes.

值得注意。 Bounded to 32 concurrent streams - the 33rd gets 503 - and the server CLOSES every stream after five minutes. A client that does not reconnect simply stops receiving, with no error.

any

OPTIONS
Params
none
返回
204

The preflight. Allowed methods are GET and OPTIONS, allowed header is Content-Type.

值得注意。 403 when an Origin is present and not on the allowlist, rather than a 204 without the allow header.

any

POST
Params
none
返回
405

This API is read-only and answers 405 to every POST, in JSON and with the CORS headers.

值得注意。 It had one write route: a token-metadata edit signed by the contract's owner. It is gone, along with the form that called it, because an explorer that takes visitor-supplied identity for an asset is an impersonation surface.

限制、分页与缓存

限制Value
Request rate300 per minute per client addressthen 429; the window is wall-clock and resets on the minute
Client identitythe rightmost trusted X-Forwarded-For entryindexed from the right by the number of trusted proxy hops, because the leftmost entry is whatever the client wrote
Request body600,000 bytesthere is nothing to POST, but the cap exists
List paginglimit <= 100, offset >= 0a non-numeric limit silently becomes the default rather than erroring
Live streams32 concurrent, 300 seconds each503 above the first, silent close at the second
Answer cacheabout 3 secondson /address, /tokens, /nfts and the NFT routes; the stats cache is shorter

速率限制是按客户端地址计的,而且和浏览器自己的页面共用

每分钟三百个请求,对一个人来说很宽裕,对一次回填来说很紧。那个窗口是按挂钟的:它在整分钟 重置而不是滑动,所以一次卡在分钟交界处的突发可以在两秒里花掉两个窗口的量,然后在第二个窗口 剩下的时间里一直回答 429。这个服务上没有 retry-after 响应头,请自己退避。

计数背后的身份是转发来的客户端地址,从这条链的右端读取,因为最左边那一项是调用者自己写 什么就是什么。在一个不追加的代理后面,每一个调用者都会塌缩成一个桶,于是整个互联网共用一份 预算。

分页用的是 limit 和 offset,钳制在一百。一个非数字的 limit 会变成 默认值而不是一个错误,而一个负数会变成一,所以一个格式错误的请求得到的是一个看起来合理的 答案,而不是一句抱怨。多数列表路由不返回总数;/minis 和 /accounts 是例外。

答案会被缓存几秒

/address、/tokens、/nfts 和那些 NFT 路由被放在一个 以路径和分页为键的短命缓存里,而 /stats 由一个后台线程重新计算,并从一个更短 的缓存里提供。同一瞬间的两个相同请求会给出相同的答案,这对一个页面没问题,对一个确认循环 就是错的。请去向节点轮询回执,而不是这里。

新鲜度与落后量

/stats 带着那些说明索引有多新的数字:indexedBlock 对 latestBlock、作为两者之差的 indexLag,以及给那些物化视图用的 derivedLag,代币余额和 NFT 归属由单独的工作进程构建,可能落后于它们所来自的 那些交易。

bash
# Is the archive current? Compare the two, do not trust either alone.
curl -s "$EXPLORER_API/stats" | jq '{latestBlock, indexedBlock, indexLag, derivedLag}'

# One transaction, whole, traces included. This is the route with no substitute.
curl -s "$EXPLORER_API/tx/$HASH" | jq '{success, decoded, traces: (.traces|length), tokenTransfers}'

# Page an address's history by offset - and see the note below before relying on it.
curl -s "$EXPLORER_API/address/$ADDR?limit=100&offset=0" | jq '.transactions | length'

偏移量分页会在一份增长的列表下面挪动

这里每一份列表都是最新在前,而新行到达头部。因此在第一页之后一会儿取到的第二页会和它重叠, 而且在你往下走的过程中有些行可能被整个跳过。对一次必须完整的回填,请按区块号分页并向下走, 或者一次取一个区块;offset 是给用户界面用的,不是给导入程序用的。

在你拿任何东西做键之前,还有一处不对称值得知道:这条链按交易而不是按区块给 logIndex 编号,所以 (blockNumber, logIndex) 这个二元组并不唯一。 请把交易哈希加进你构造的任何键里。