金融与交易
在 Solana 移动应用中展示 .skr…
适用于 Solana(尤其 Seeker)移动应用中,在资料、好友列表、交易历史或支付输入里把 .skr 域名与钱包地址互相解析,并按场景安全展示和缓存。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 Solana 移动应用中展示 .sk特定
解决思路
- 明确 .skr 是 Solana mainnet 上的 AllDomains 名称;实现两个方向:正向 alice.skr → 钱包地址,反向钱包地址 → 该地址拥有的 .skr 名称。
- 不论应用其他部分连接哪个 cluster(包括 devnet),.skr 解析都必须针对 mainnet。
- 选择解析执行位置:原型/低流量可用客户端直接调用公共 RPC;面向生产默认走后端代理。
- 需要保护 RPC key、共享缓存、批量查询、访问 getProgramAccounts 时,走后端代理;EXPO_PUBLIC_* 中的 key 可被任何人从 APK 读取,付费 RPC 必须服务端。
- 若项目不明显,询问用户选择客户端直连还是代理;任何上生产的方案默认代理。
- 写新服务前先检查现有后端:在每个 package.json 查找 express、fastify、hono、@nestjs/core、koa 或带 API routes 的 Next.js。
- 查找入口文件:server.ts、app.ts、main.ts、index.ts。
- 查找路由组织:routes/、api/、controllers/。
- 若仍不明确就询问用户,例如“我看到 apps/api 里有 Fastify server;.skr 端点应加在那里吗?”
- 把路由加到已有后端并匹配其 routing、validation、error handling 约定;只有在确实没有后端时才 scaffold 最小 server。
- 默认用 Kit 解析:npm install @solana/kit "@noble/hashes@^1"。
- 将 @noble/hashes pin 到 ^1;新版 2.x 的 exports map 去掉无扩展名 ./sha2 子路径;resolver 导入 @noble/hashes/sha2.js,两个 major 都接受。
- 从 references/kit-resolver.md 复制实现(约 140 行,tsc --strict 通过,无 Buffer/TextEncoder),使同一文件可运行在服务端和 React Native。
- 用 createSolanaRpc(process.env.SOLANA_MAINNET_RPC_URL) 创建始终 mainnet 的 rpc。
- 调用 resolveSkrDomain(rpc, 'alice.skr') 返回 Address 或 null;调用 resolveSkrNames(rpc, address('5FHw...')) 返回排序后的名称数组。
- Kit helper 接受 alice.skr 或 alice,未注册返回 null,仅 RPC 失败时 reject。
- 需要 ANS records、avatars 或用户 MainDomain 时,不要用轻量 Kit helper,改用 SDK/@onsol/tldparser。
- 备选 @onsol/tldparser:npm install @onsol/tldparser @solana/web3.js;用 new Connection(process.env.SOLANA_MAINNET_RPC_URL, 'confirmed') 和 new TldParser(connection)。
- 正向 @onsol/tldparser 调用 getOwnerFromDomainTld 必须传完整域名(含 .skr),如 alice.skr;传 alice 会抛错,因为 SDK 按 . 分割并把第二段当 TLD,bare name 会在 .undefined 下派生 PDA。
- @onsol/tldparser 的 getOwnerFromDomainTld 不返回 null 而抛错;未注册和 malformed 输入不可区分,均表现为 TypeError: Cannot read properties of undefined (reading 'owner')。每次调用包 try/catch,绝不要按 falsy 返回值分支。
- 要区分未注册与 malformed,调用 getNameRecordFromDomainTld(domain);缺失 account 时它干净返回 undefined。
- 反向 @onsol/tldparser 调用 getParsedAllUserDomainsFromTld 时 TLD 不带点:skr 可用,.skr 会静默返回 [];结果里的 domain 字段已包含后缀。
- 反向查询返回数组;一个地址可拥有多个 .skr,顺序不是排名。排序后取第一个,否则显示名称会在多次调用间变化;排序只让 label 稳定,不代表可信。
- 若用 @onsol/tldparser,其 ESM build 有问题;参考 references/server.md 的 createRequire workaround。
- API 提供两个端点(按现有框架适配):POST /api/resolve-domain,body { "domain": "alice.skr" },成功 { "address" },未找到 404;POST /api/resolve-address,body { "address": "5FHw..." },成功 { "domain" },未找到 404。
- 触碰 RPC 前验证输入:格式错误的 base58 地址或不以 .skr 结尾的域名返回 400,避免坏输入消耗 RPC quota。
- 区分“没有注册域名”(404)和“RPC 失败”(503);不要把两者都折叠为 404,否则 outage 看起来像所有用户都没有名字。
- 代理不能让自身变成 RPC key 前的 open relay。反向路由成本包含 getProgramAccounts 加上对该地址拥有的每个名称的批量读取,因此端点需要 origin allowlist、per-IP rate limit、body limit、缓存(含 negative results)。启动时要求 RPC URL 和 origin list,不要回退公共 endpoint 或开放 CORS。
- 参考 references/server.md 的 Express/Hono 完整实现,以及 Fastify、NestJS、Koa、Next.js route handlers 注意事项。
- 客户端使用解析 hook:const { data: domain } = useResolveAddress(account?.address);const label = domain ?? ellipsify(account?.address)。
- 始终回退到截断地址;解析失败应降级到可用内容,绝不显示空白或永不结束的 spinner。
- Android emulator 中 localhost 是模拟器自身,用 http://10.0.2.2:3000 访问宿主机;物理设备用宿主机 LAN IP。
- 不要把地址硬编码进源码;从 EXPO_PUBLIC_API_URL 读取,并把任何 emulator fallback 用 __DEV__ gate。EXPO_PUBLIC_* 在构建时内联,未 gate 的默认值会在 release APK 中带上失效 cleartext URL,Android 默认阻止 cleartext;任何含 RPC key 的东西都不要放进 EXPO_PUBLIC_*。
- 如果客户端直连解析而不是走代理,Kit resolver 在 Hermes 下原样运行;在同一个 hook 中调用它替代 fetch。
- 参考 references/client.md 的 hook、components 和 truncation helper。
- 反向解析的名称只是地址碰巧持有的排序最靠前的名称;.skr transfer 不需要接收方做什么,任何人都可把名称推给任意钱包,因此陌生人可通过注册排序靠前的名称并发送来决定 UI 如何称呼用户。
- 把名称显示在截断地址旁边,而不是代替地址;地址才是用户能实际核对的。
- 当 label 代表身份(payee、counterparty、moderation surface)时,优先使用 owner 选择的 MainDomain;用 @onsol/tldparser 的 getMainDomain,用户未设置时会 throw,将 throw 视为“无”并回退地址。
- 反向查询必须尊重 expiry;已过期但仍能解析的名称会继续给地址贴上 owner 已失去的名称。
- 按方向缓存:正向 name → address 用于 payment destinations,不缓存;发送时重新解析。
- 反向 address → name 用于显示 label,可设长 staleTime;一小时即可。
- 名称很少变化,缓存反向结果几乎免费;正向结果不同:.skr 可转移、可重新注册,缓存一小时后再用于构造 transfer 会付款给一小时前的 owner,UI 不会显得异常。
- 签名前立即重新解析,并把解析出的地址放进确认步骤,让用户看到资金实际去向。
- 缓存必须双侧遵守:客户端发送时重新解析,但如果代理从自己的 forward cache 回答就无效;服务端只缓存 forward misses,绝不要缓存已解析的 address。
- 参考 references/kit-resolver.md、references/server.md、references/client.md;相关 skills 包括 solana-mobile-wallet 和 seeker-genesis-token。
适用边界 · 注意事项
- 不适用于非 Solana 或非 .skr 域名体系;需要其他链或其他命名系统解析时不要用本方案。
- 需要 ANS records、avatars 或 MainDomain 时,不要只用默认轻量 Kit helper;生产环境或列表视图也不要直接依赖公共 RPC 客户端解析。
- 不要把反向解析出的 .skr 名称当作唯一身份或支付依据;也不要把正向解析结果缓存后用于转账,或把未注册与 RPC 失败都返回 404。