介绍键值存储:无需重新部署即可修改关注列表
Key-Value Store 为您的数据管道在Quicknode 上提供了一个持久且可更新的状态层。您可以通过 REST API 更新观察列表,而无需修改过滤器代码或重新部署Streams 。

观察名单会发生变化。每当有人注册时,投资组合追踪工具就会新增一个地址。合规流程则依据一份制裁名单进行,而该名单的更新时间由他人决定。
如果该列表存储在你的 `Streams ` 过滤器中,那么每次更改都会变成代码修改。有人编辑了一个数组,就会更新该过滤器。或者,你将数据保存在一个独立的数据库中,并在每个代码块中查询它,这又会让你需要维护和同步另一个系统。
键值存储将这种状态变化从过滤器中移出。
它提供了两种数据类型:
列表用于存储命名好的字符串项集合,例如钱包地址、白名单或过滤条件。
值包含一个需要随时间推移进行追踪的状态项,例如你处理的最后一个区块。
Streams 过滤器既可以读取也可以写入。受支持的 Webhook 模板可以按名称引用键值存储列表。后端、脚本或agent 均可通过 REST API 访问相同的数据。
对于观察列表而言,这意味着只需一次 API 调用,即可更改正在运行的过滤器所匹配的内容,而无需更改或重新部署该过滤器本身。
避免更换过滤器只是其优势之一。更重要的是,无论谁拥有该观察列表,都无需在数据发生变化时每次都修改过滤逻辑。用户界面、后端或脚本均可直接对其进行更新。
所有Quicknode 套餐均支持键值存储。
在Streams 过滤器中,您可以使用qnLib.qnContainsListItems方法将多个项目与列表进行比对:
async function main(payload) {
const addresses = payload.data.flatMap(block =>
block.transactions.flatMap(tx => [tx.from, tx.to])
);
const hits = await qnLib.qnContainsListItems(
"watched_wallets",
addresses
);
return hits.some(Boolean) ? payload.data : null;
}该方法接受一个项目数组,并针对每个项目返回一个布尔值,其返回结果与输入数组保持对齐。过滤器也可以用 Go 语言编写,其中等效的方法是 qn.ContainsListItems,该方法以同步方式运行,无需使用 await 关键字。
关键点在于 watched_wallets 的位置:它在过滤器之外。
在列表中添加或移除一个地址后,正在运行的过滤器会自动使用更新后的观察列表,无需重新部署。
只要过滤逻辑保持不变,而所处理的数据发生变化,这种模式在任何地方都适用。
列表中不必包含钱包地址。
它们还可以包含用于确定哪些事件重要的标准。例如,一个订单监控应用程序可能会允许用户选择他们想要跟踪的订单状态。
与其将这些状态硬编码到过滤器中,不如将它们存储在一个列表中。当用户更改选择时,更新该列表,正在运行的过滤器就会开始使用新的条件。
同样的思路也适用于白名单、黑名单、路由规则、受监控的合约,或是其他与您的过滤逻辑独立变化的值集。
如果修改某项内容无需更改过滤器本身,那么该内容就是键值存储的理想候选对象。
价值观体现了同一理念的另一面。
例如,一个需要记住上次处理结束位置的过滤器,可以在运行结束时写入一个“lastProcessedBlock”值,并在处理恢复时再次读取该值。
过滤器无需将状态变化嵌入到应用程序逻辑中,而是可以通过键值存储来读取和更新状态。
在过滤器中使用键值存储之前,有几点值得了解。
键值存储中的项目区分大小写。
对于区块链地址,请确保以一致的方式存储和验证其值。否则,大小写不同的地址可能无法按预期匹配。
键值存储可让您的过滤器访问列表的当前内容,因此当当前状态至关重要时,它便非常适合——许多关注列表和动态过滤规则正是如此。
更新列表时,正在运行的筛选器会读取更新后的内容。
Streams 过滤器可以通过Streams 运行时访问键值存储。
直接通过 REST API 发起的请求(无论是读取还是写入),都需要使用Quicknode API 密钥。
在Streams 过滤器中对键值存储进行的读取和比较操作不会消耗API配额。使用带Webhook的键值存储列表也是免费的。
写入操作有所不同。无论写入操作是通过Streams 过滤器还是通过REST API进行的,添加列表项或创建值都会消耗API配额。
以下用法会消耗 API 积分:
每添加一个列表项或生成一个值,可获得20 个 API 积分
每月每项存储项目可获得10 个 API 积分
每次对键值存储 REST API 的请求消耗5 个 API 积分
当前的大小限制包括:每个列表项最多 128 个字符,每个值最多800,000 个字符。
在规划生产环境的使用规模之前,请查阅键值存储文档,了解最新的定价和限制信息。
将现有数组迁移到键值存储中需要修改一个过滤器。
首先,创建列表并为其初始化:
curl -X POST "https://api.quicknode.com/kv/rest/v1/lists" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"key":"watched_wallets","items":["0x8f3c...","0x41be..."]}'您可以在一次请求中创建列表并为其添加初始数据。
然后将过滤器设置为从该列表中读取数据,并更新一次。
此后,观察列表的更改将通过键值存储(Key-Value Store)进行,而非通过过滤器。
对于持续更新或批量修改,更新列表(endpoint )可在单个 PATCH 请求中添加和移除多个项目。这使得 UI、后端、脚本或 CI 任务能够轻松地保持列表的最新状态,而无需修改过滤器。
键值存储(Key-Value Store)的数据作用域限定在Quicknode 账户内,而非单个项目或endpoint ,因此Streams 过滤器、Webhooks 以及应用程序均可基于同一底层数据运行。
“钱包追踪”功能通过Solana 和Ethereum 上的实时钱包观察列表展示相关趋势。地址在过滤器之外进行管理,可通过应用程序界面进行更新,无需重新部署 Stream。

“钱包追踪”示例应用,此处展示于 UserStream 演示界面中。
HyperCore 订单监控器将这一理念应用于Hyperliquid 核心订单,利用键值存储列表对地址和订单状态进行动态筛选。

如果你想了解该模式在完整应用程序中的应用,这两者都是很有用的切入点。
凡是因用户改变主意,或因其他系统发布了新内容而发生变化的情况,都值得关注。
钱包地址就是最明显的例子。但白名单、黑名单、受监控的合约、路由规则、用户选择的事件类型以及类似的配置都可以遵循相同的模式。
区别很简单:
如果逻辑发生了变化,请修改过滤器。
如果只有数据会发生变化,建议将其存储在键值存储中。
将数据导出一次,更新过滤条件,之后让它独立变化。
Quicknode 成立于 2017 年,为开发者和企业提供机构级区块链基础设施。凭借 99.99% 的运行时间以及对 77 条以上区块链的支持,团队能够毫无妥协地构建和扩展链上应用程序。
将最新的工程见解、产品更新和 Web3 资讯直接发送至您的收件箱。
📚 新书:《在……上构建金融软件》Solana免费电子书,内含10套完整的交易策略,涵盖期权到永续合约。
获取一份通过 SOC 2 II 类认证 · ISO 27001