TaskMarket
多伦多本地「自有数据」市场。餐馆、房东等数据主人出售自己经营的聚合数据,买方先看样本再买,每次交付都要先通过 schema 和隐私下限校验才能结算。后端已用 Rust 重写。
背景
TaskMarket 最初是给留学生用的任务市场,在 Base 链上用 USDC 托管付款。2026 年 9 月,我围绕一个问题重新定位了它:结算能不能被代码验证? 跑腿类任务基本做不到;数据可以,因为一次交付要么符合约定的 schema 和隐私规则,要么不符合。
所以 TaskMarket 现在是多伦多的本地自有数据市场。一家餐馆、一位房东、一名司机,出售关于自己经营的聚合数据。买方付款前先看样本,交付要通过自动校验才会结算。抓取来的数据不在范围内,只有数据的主人才能上架。
截图均为 3840×2160,也就是在 32 寸 4K 显示器上的样子。数据市场相关页面来自本地实例,用的是项目自带的合成示例商品,页面上标有「示例」;采集任务页面来自线上网站,其中的开放任务是自动生成的示例。
做法
能被代码验证的结算
每个商品都带一份 JSON Schema 和一条聚合下限,比如「每一行至少覆盖 5 家店」,这样任何单一商家都不会被识别出来。买方付款(开票或 USDC)后,卖方以 JSON 或 CSV 上传交付:
- 数据行用 Ajv 按 schema 校验,聚合下限逐行检查。
- 通过:订单结算,买方可以下载文件。
- 不通过:交付被拒,附上逐行的错误说明,卖方修正后可以重新交付。
- 每次交付都会保存数据的 SHA-256 哈希;交付文件只有买方能下载,不会作为公开的静态文件提供。
卖方上架前要用钱包签署一份数据授权模板;授权可以撤回,撤回后相关商品会自动下架。
用采集任务补上空白
还不存在的数据,可以到现场去采集。原来的任务市场改成了采集任务,共七类:人流计数、门店核查、神秘顾客、问卷、价格采集、信息核实和地推推广。任务仍然走竞价订单簿,发布者能比较价格、时间和过往记录,而不是谁先回复就选谁;USDC 付款仍可以走 Base 上的托管合约。
用旧后端来证明的 Rust 后端
我把 Express 后端用 Rust(axum、sqlx、socketioxide)重写成可以直接替换的版本:同一个数据库、同样的 JSON、同样的 Socket.IO 事件,前端一行都不用改。旧的 Node 代码就是规格说明:
- 差分测试台对两个后端回放 933 个场景,逐一比较状态码和响应内容,另外还有 48 个 Socket.IO 检查点。
- 切换前,Rust 后端在生产数据库的副本上,对线上各个接口的响应与 Node 完全一致。
- 2026 年 9 月 10 日正式上线,靠一行配置就能切回 Node。
唯一有意改变的行为是修了一个问题:以前订单在被取消或进入争议之后,仍可能被自动确认,进而触发托管资金放款。
快速的公开页面
公开页面在 Cloudflare Pages Functions 上做服务端渲染,并用结构化数据把每个商品标记为 Dataset。拆分打包后,首屏 JavaScript 从 257 KB 降到 122 KB(gzip),钱包相关代码只有在打开钱包流程时才加载。
结果与收获
已上线,运行在 taskmarket.pages.dev。 数据市场已经开放,并且是刻意从空开始的:示例商品不应该出现在一个承诺真实数据的市场里。与本地餐馆的试点在 2026 年 9 月启动。
- 选一个结算能被验证的市场。 争议是任何市场里最贵的部分。schema 加隐私下限,把「这样够不够好」变成了一个几毫秒就能跑完的检查。
- 重写要对照差分测试,而不是凭记忆。 旧后端就是规格。933 个回放场景让切换变成一次配置修改,而不是一次冒险,过程中还抓出了一个真实的资金问题。
- 空货架胜过假货架。 塞进示例商品会让市场看起来更热闹,却会让每一个商品都更不可信。
技术栈与链接
前端: React 19 · Vite 7 · Tailwind 4 · Cloudflare Pages Functions(SSR)
后端: Rust · axum · sqlx · SQLite · socketioxide · Ajv(交付校验)
链上: Base 上的 Solidity 托管合约 · viem