tapimo 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/README.md +36 -8
  2. package/dist/ApiKey.d.ts +1 -0
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +5 -2
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +28 -1
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +34 -1
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +7532 -4850
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +11 -3
  13. package/dist/App.js.map +1 -1
  14. package/dist/Scope.d.ts +11 -2
  15. package/dist/Scope.d.ts.map +1 -1
  16. package/dist/Scope.js +14 -3
  17. package/dist/Scope.js.map +1 -1
  18. package/dist/admin/App.d.ts +63 -53
  19. package/dist/admin/App.d.ts.map +1 -1
  20. package/dist/admin/apps/api-keys.d.ts +7 -0
  21. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  22. package/dist/admin/apps/scopes.d.ts +8 -0
  23. package/dist/admin/apps/scopes.d.ts.map +1 -1
  24. package/dist/admin/apps/scopes.js +3 -0
  25. package/dist/admin/apps/scopes.js.map +1 -1
  26. package/dist/admin/apps/verified-tokens.d.ts +57 -57
  27. package/dist/admin/ui.generated.d.ts +1 -1
  28. package/dist/admin/ui.generated.js +13 -13
  29. package/dist/admin/ui.generated.js.map +1 -1
  30. package/dist/analytics/Analytics.d.ts +151 -0
  31. package/dist/analytics/Analytics.d.ts.map +1 -0
  32. package/dist/analytics/Analytics.js +212 -0
  33. package/dist/analytics/Analytics.js.map +1 -0
  34. package/dist/analytics/tables/requestEvents.d.ts +215 -0
  35. package/dist/analytics/tables/requestEvents.d.ts.map +1 -0
  36. package/dist/analytics/tables/requestEvents.js +264 -0
  37. package/dist/analytics/tables/requestEvents.js.map +1 -0
  38. package/dist/apps/data/App.d.ts +1049 -624
  39. package/dist/apps/data/App.d.ts.map +1 -1
  40. package/dist/apps/data/App.js +36 -0
  41. package/dist/apps/data/App.js.map +1 -1
  42. package/dist/apps/data/FundingRouteProviders.d.ts +54 -0
  43. package/dist/apps/data/FundingRouteProviders.d.ts.map +1 -0
  44. package/dist/apps/data/FundingRouteProviders.js +355 -0
  45. package/dist/apps/data/FundingRouteProviders.js.map +1 -0
  46. package/dist/apps/data/index.d.ts +1 -0
  47. package/dist/apps/data/index.d.ts.map +1 -1
  48. package/dist/apps/data/index.js +1 -0
  49. package/dist/apps/data/index.js.map +1 -1
  50. package/dist/apps/data/routes/balances.d.ts +45 -45
  51. package/dist/apps/data/routes/coingecko.d.ts +176 -176
  52. package/dist/apps/data/routes/exchanges.d.ts +455 -455
  53. package/dist/apps/data/routes/fee-amm.d.ts +101 -101
  54. package/dist/apps/data/routes/funding.d.ts +843 -0
  55. package/dist/apps/data/routes/funding.d.ts.map +1 -0
  56. package/dist/apps/data/routes/funding.js +443 -0
  57. package/dist/apps/data/routes/funding.js.map +1 -0
  58. package/dist/apps/data/routes/indexer.d.ts +5 -5
  59. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  60. package/dist/apps/data/routes/receipts.js +2 -8
  61. package/dist/apps/data/routes/receipts.js.map +1 -1
  62. package/dist/apps/data/routes/rpc.d.ts +29 -36
  63. package/dist/apps/data/routes/rpc.d.ts.map +1 -1
  64. package/dist/apps/data/routes/rpc.js +29 -1
  65. package/dist/apps/data/routes/rpc.js.map +1 -1
  66. package/dist/apps/data/routes/tokenlist.d.ts +36 -36
  67. package/dist/apps/data/routes/transfers.d.ts +56 -56
  68. package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
  69. package/dist/apps/data/routes/webhooks.d.ts +45 -45
  70. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  71. package/dist/apps/data/routes/webhooks.js +8 -8
  72. package/dist/apps/data/routes/webhooks.js.map +1 -1
  73. package/dist/apps/docs/App.d.ts +5 -3
  74. package/dist/apps/docs/App.d.ts.map +1 -1
  75. package/dist/apps/docs/App.js +28 -96
  76. package/dist/apps/docs/App.js.map +1 -1
  77. package/dist/apps/docs/reference.d.ts +21 -0
  78. package/dist/apps/docs/reference.d.ts.map +1 -0
  79. package/dist/apps/docs/reference.js +112 -0
  80. package/dist/apps/docs/reference.js.map +1 -0
  81. package/dist/apps/index.d.ts +3 -2
  82. package/dist/apps/index.d.ts.map +1 -1
  83. package/dist/apps/index.js +3 -2
  84. package/dist/apps/index.js.map +1 -1
  85. package/dist/apps/{platform → management}/App.d.ts +3015 -738
  86. package/dist/apps/management/App.d.ts.map +1 -0
  87. package/dist/apps/{platform → management}/App.js +20 -10
  88. package/dist/apps/management/App.js.map +1 -0
  89. package/dist/apps/management/Billing.d.ts +279 -0
  90. package/dist/apps/management/Billing.d.ts.map +1 -0
  91. package/dist/apps/management/Billing.js +477 -0
  92. package/dist/apps/management/Billing.js.map +1 -0
  93. package/dist/apps/management/index.d.ts +3 -0
  94. package/dist/apps/management/index.d.ts.map +1 -0
  95. package/dist/apps/management/index.js +3 -0
  96. package/dist/apps/management/index.js.map +1 -0
  97. package/dist/apps/{platform → management}/routes/api-keys.d.ts +341 -49
  98. package/dist/apps/management/routes/api-keys.d.ts.map +1 -0
  99. package/dist/apps/{platform → management}/routes/api-keys.js +116 -14
  100. package/dist/apps/management/routes/api-keys.js.map +1 -0
  101. package/dist/apps/management/routes/billing.d.ts +1520 -0
  102. package/dist/apps/management/routes/billing.d.ts.map +1 -0
  103. package/dist/apps/management/routes/billing.js +795 -0
  104. package/dist/apps/management/routes/billing.js.map +1 -0
  105. package/dist/apps/{platform → management}/routes/invitations.d.ts +202 -84
  106. package/dist/apps/management/routes/invitations.d.ts.map +1 -0
  107. package/dist/apps/{platform → management}/routes/invitations.js +59 -1
  108. package/dist/apps/management/routes/invitations.js.map +1 -0
  109. package/dist/apps/{platform → management}/routes/me.d.ts +17 -17
  110. package/dist/apps/management/routes/me.d.ts.map +1 -0
  111. package/dist/apps/management/routes/me.js.map +1 -0
  112. package/dist/apps/management/routes/members.d.ts.map +1 -0
  113. package/dist/apps/management/routes/members.js.map +1 -0
  114. package/dist/apps/{platform → management}/routes/orgs.d.ts +50 -36
  115. package/dist/apps/management/routes/orgs.d.ts.map +1 -0
  116. package/dist/apps/{platform → management}/routes/orgs.js +14 -3
  117. package/dist/apps/management/routes/orgs.js.map +1 -0
  118. package/dist/apps/{platform → management}/routes/projects.d.ts +97 -97
  119. package/dist/apps/{platform → management}/routes/projects.d.ts.map +1 -1
  120. package/dist/apps/management/routes/projects.js.map +1 -0
  121. package/dist/apps/management/routes/scopes.d.ts +107 -0
  122. package/dist/apps/management/routes/scopes.d.ts.map +1 -0
  123. package/dist/apps/management/routes/scopes.js +66 -0
  124. package/dist/apps/management/routes/scopes.js.map +1 -0
  125. package/dist/apps/management/routes/usage.d.ts +588 -0
  126. package/dist/apps/management/routes/usage.d.ts.map +1 -0
  127. package/dist/apps/management/routes/usage.js +391 -0
  128. package/dist/apps/management/routes/usage.js.map +1 -0
  129. package/dist/apps/mcp.d.ts +76 -0
  130. package/dist/apps/mcp.d.ts.map +1 -0
  131. package/dist/apps/mcp.js +188 -0
  132. package/dist/apps/mcp.js.map +1 -0
  133. package/dist/apps/relay/App.d.ts +4 -1
  134. package/dist/apps/relay/App.d.ts.map +1 -1
  135. package/dist/apps/relay/App.js +118 -10
  136. package/dist/apps/relay/App.js.map +1 -1
  137. package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
  138. package/dist/apps/relay/Sponsorships.js +2 -1
  139. package/dist/apps/relay/Sponsorships.js.map +1 -1
  140. package/dist/cli/Cli.d.ts +8 -1
  141. package/dist/cli/Cli.d.ts.map +1 -1
  142. package/dist/cli/Cli.js +11 -3
  143. package/dist/cli/Cli.js.map +1 -1
  144. package/dist/cli/commands/admin.d.ts +4 -0
  145. package/dist/cli/commands/admin.d.ts.map +1 -1
  146. package/dist/cli/commands/admin.js +80 -1
  147. package/dist/cli/commands/admin.js.map +1 -1
  148. package/dist/db/Db.d.ts +7 -0
  149. package/dist/db/Db.d.ts.map +1 -1
  150. package/dist/db/Db.js +126 -0
  151. package/dist/db/Db.js.map +1 -1
  152. package/dist/db/Schema.d.ts +79 -0
  153. package/dist/db/Schema.d.ts.map +1 -1
  154. package/dist/db/Schema.js +88 -2
  155. package/dist/db/Schema.js.map +1 -1
  156. package/dist/db/tables/billingSettings.d.ts +55 -0
  157. package/dist/db/tables/billingSettings.d.ts.map +1 -0
  158. package/dist/db/tables/billingSettings.js +70 -0
  159. package/dist/db/tables/billingSettings.js.map +1 -0
  160. package/dist/db/tables/invitations.js +2 -2
  161. package/dist/db/tables/invitations.js.map +1 -1
  162. package/dist/db/tables/organizations.d.ts +6 -2
  163. package/dist/db/tables/organizations.d.ts.map +1 -1
  164. package/dist/db/tables/organizations.js +10 -4
  165. package/dist/db/tables/organizations.js.map +1 -1
  166. package/dist/db/tables/projects.js +2 -2
  167. package/dist/db/tables/projects.js.map +1 -1
  168. package/dist/db/tables/requestUsage.d.ts +121 -0
  169. package/dist/db/tables/requestUsage.d.ts.map +1 -0
  170. package/dist/db/tables/requestUsage.js +150 -0
  171. package/dist/db/tables/requestUsage.js.map +1 -0
  172. package/dist/db/tables/sponsoredTransactions.d.ts +119 -0
  173. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  174. package/dist/db/tables/sponsoredTransactions.js +155 -2
  175. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  176. package/dist/db/tables/stripeCustomers.d.ts +81 -0
  177. package/dist/db/tables/stripeCustomers.d.ts.map +1 -0
  178. package/dist/db/tables/stripeCustomers.js +120 -0
  179. package/dist/db/tables/stripeCustomers.js.map +1 -0
  180. package/dist/db/tables/users.js +2 -2
  181. package/dist/db/tables/users.js.map +1 -1
  182. package/dist/handlers/internal/sponsorship.d.ts +5 -2
  183. package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
  184. package/dist/handlers/internal/sponsorship.js +19 -5
  185. package/dist/handlers/internal/sponsorship.js.map +1 -1
  186. package/dist/handlers/internal/utils.d.ts +10 -3
  187. package/dist/handlers/internal/utils.d.ts.map +1 -1
  188. package/dist/handlers/internal/utils.js +14 -6
  189. package/dist/handlers/internal/utils.js.map +1 -1
  190. package/dist/index.d.ts +1 -0
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.js +1 -0
  193. package/dist/index.js.map +1 -1
  194. package/dist/internal/Auth.d.ts +18 -4
  195. package/dist/internal/Auth.d.ts.map +1 -1
  196. package/dist/internal/Auth.js +149 -77
  197. package/dist/internal/Auth.js.map +1 -1
  198. package/dist/internal/Cache.d.ts.map +1 -1
  199. package/dist/internal/Cache.js +4 -1
  200. package/dist/internal/Cache.js.map +1 -1
  201. package/dist/internal/EdgeCache.d.ts +10 -0
  202. package/dist/internal/EdgeCache.d.ts.map +1 -1
  203. package/dist/internal/EdgeCache.js +39 -8
  204. package/dist/internal/EdgeCache.js.map +1 -1
  205. package/dist/internal/Fees.d.ts +27 -0
  206. package/dist/internal/Fees.d.ts.map +1 -0
  207. package/dist/internal/Fees.js +48 -0
  208. package/dist/internal/Fees.js.map +1 -0
  209. package/dist/internal/FundingRoutes.d.ts +915 -0
  210. package/dist/internal/FundingRoutes.d.ts.map +1 -0
  211. package/dist/internal/FundingRoutes.js +625 -0
  212. package/dist/internal/FundingRoutes.js.map +1 -0
  213. package/dist/internal/Id.d.ts +15 -0
  214. package/dist/internal/Id.d.ts.map +1 -0
  215. package/dist/internal/Id.js +22 -0
  216. package/dist/internal/Id.js.map +1 -0
  217. package/dist/internal/Log.d.ts +2 -0
  218. package/dist/internal/Log.d.ts.map +1 -1
  219. package/dist/internal/Log.js +3 -0
  220. package/dist/internal/Log.js.map +1 -1
  221. package/dist/internal/OpenApi.d.ts +10 -1
  222. package/dist/internal/OpenApi.d.ts.map +1 -1
  223. package/dist/internal/OpenApi.js +8 -1
  224. package/dist/internal/OpenApi.js.map +1 -1
  225. package/dist/internal/RateLimit.d.ts +25 -0
  226. package/dist/internal/RateLimit.d.ts.map +1 -1
  227. package/dist/internal/RateLimit.js +51 -0
  228. package/dist/internal/RateLimit.js.map +1 -1
  229. package/dist/internal/Response.d.ts +1 -1
  230. package/dist/internal/Response.d.ts.map +1 -1
  231. package/dist/internal/Schema.d.ts +8 -0
  232. package/dist/internal/Schema.d.ts.map +1 -1
  233. package/dist/internal/Schema.js +7 -0
  234. package/dist/internal/Schema.js.map +1 -1
  235. package/dist/internal/Webhooks.d.ts.map +1 -1
  236. package/dist/internal/Webhooks.js +3 -3
  237. package/dist/internal/Webhooks.js.map +1 -1
  238. package/package.json +8 -7
  239. package/src/ApiKey.ts +9 -2
  240. package/src/ApiKeys.test.ts +51 -0
  241. package/src/ApiKeys.ts +50 -1
  242. package/src/App.test.ts +33 -86718
  243. package/src/App.ts +26 -8
  244. package/src/Client.test-d.ts +353 -2
  245. package/src/Scope.ts +16 -3
  246. package/src/admin/apps/scopes.test.ts +6 -0
  247. package/src/admin/apps/scopes.ts +3 -0
  248. package/src/admin/ui/src/components/Page.tsx +2 -3
  249. package/src/admin/ui/src/routes/__root.tsx +2 -2
  250. package/src/admin/ui/src/routes/api-keys.tsx +2 -2
  251. package/src/admin/ui.generated.ts +13 -13
  252. package/src/analytics/Analytics.test.ts +527 -0
  253. package/src/analytics/Analytics.ts +318 -0
  254. package/src/analytics/tables/requestEvents.ts +523 -0
  255. package/src/apps/composition.test.ts +26 -13
  256. package/src/apps/data/App.test.ts +72 -0
  257. package/src/apps/data/App.ts +37 -0
  258. package/src/apps/data/FundingRouteProviders.test.ts +281 -0
  259. package/src/apps/data/FundingRouteProviders.ts +459 -0
  260. package/src/apps/data/index.ts +1 -0
  261. package/src/apps/data/routes/funding.test.ts +314 -0
  262. package/src/apps/data/routes/funding.ts +698 -0
  263. package/src/apps/data/routes/receipts.ts +2 -9
  264. package/src/apps/data/routes/rpc.test.ts +78 -2
  265. package/src/apps/data/routes/rpc.ts +31 -1
  266. package/src/apps/data/routes/webhooks.test.ts +1 -1
  267. package/src/apps/data/routes/webhooks.ts +11 -8
  268. package/src/apps/docs/App.ts +30 -101
  269. package/src/apps/docs/reference.ts +132 -0
  270. package/src/apps/index.ts +3 -2
  271. package/src/apps/{platform → management}/App.ts +56 -17
  272. package/src/apps/management/Billing.test.ts +530 -0
  273. package/src/apps/management/Billing.ts +682 -0
  274. package/src/apps/management/index.ts +2 -0
  275. package/src/apps/{platform → management}/routes/api-keys.test.ts +172 -9
  276. package/src/apps/{platform → management}/routes/api-keys.ts +137 -21
  277. package/src/apps/management/routes/billing.test.ts +1100 -0
  278. package/src/apps/management/routes/billing.ts +966 -0
  279. package/src/apps/{platform → management}/routes/invitations.test.ts +55 -7
  280. package/src/apps/{platform → management}/routes/invitations.ts +69 -1
  281. package/src/apps/management/routes/me.test.ts +351 -0
  282. package/src/apps/{platform → management}/routes/orgs.ts +26 -4
  283. package/src/apps/management/routes/scopes.test.ts +29 -0
  284. package/src/apps/management/routes/scopes.ts +85 -0
  285. package/src/apps/management/routes/usage.test.ts +422 -0
  286. package/src/apps/management/routes/usage.ts +527 -0
  287. package/src/apps/mcp.test.ts +206 -0
  288. package/src/apps/mcp.ts +250 -0
  289. package/src/apps/relay/App.test.ts +457 -8
  290. package/src/apps/relay/App.ts +120 -12
  291. package/src/apps/relay/Sponsorships.test.ts +1 -1
  292. package/src/apps/relay/Sponsorships.ts +2 -1
  293. package/src/cli/Cli.test.ts +25 -2
  294. package/src/cli/Cli.ts +17 -2
  295. package/src/cli/commands/admin.test.ts +83 -0
  296. package/src/cli/commands/admin.ts +89 -1
  297. package/src/db/Db.ts +137 -0
  298. package/src/db/Schema.ts +104 -2
  299. package/src/db/tables/billingSettings.test.ts +87 -0
  300. package/src/db/tables/billingSettings.ts +108 -0
  301. package/src/db/tables/invitations.ts +2 -2
  302. package/src/db/tables/organizations.test.ts +1 -1
  303. package/src/db/tables/organizations.ts +15 -5
  304. package/src/db/tables/projects.ts +2 -2
  305. package/src/db/tables/requestUsage.ts +231 -0
  306. package/src/db/tables/sponsoredTransactions.test.ts +108 -1
  307. package/src/db/tables/sponsoredTransactions.ts +230 -2
  308. package/src/db/tables/stripeCustomers.test.ts +109 -0
  309. package/src/db/tables/stripeCustomers.ts +162 -0
  310. package/src/db/tables/users.ts +2 -2
  311. package/src/handlers/internal/sponsorship.ts +34 -7
  312. package/src/handlers/internal/utils.ts +19 -7
  313. package/src/index.ts +1 -0
  314. package/src/internal/Auth.test.ts +175 -25
  315. package/src/internal/Auth.ts +176 -87
  316. package/src/internal/Cache.ts +5 -1
  317. package/src/internal/EdgeCache.test.ts +27 -4
  318. package/src/internal/EdgeCache.ts +47 -9
  319. package/src/internal/Fees.test.ts +32 -0
  320. package/src/internal/Fees.ts +51 -0
  321. package/src/internal/FundingRoutes.test.ts +213 -0
  322. package/src/internal/FundingRoutes.ts +898 -0
  323. package/src/internal/Id.test.ts +17 -0
  324. package/src/internal/Id.ts +24 -0
  325. package/src/internal/Log.test.ts +1 -0
  326. package/src/internal/Log.ts +5 -0
  327. package/src/internal/OpenApi.ts +12 -1
  328. package/src/internal/RateLimit.test.ts +84 -0
  329. package/src/internal/RateLimit.ts +70 -0
  330. package/src/internal/Response.ts +1 -1
  331. package/src/internal/Schema.ts +8 -0
  332. package/src/internal/Webhooks.test.ts +3 -3
  333. package/src/internal/Webhooks.ts +3 -3
  334. package/dist/apps/platform/App.d.ts.map +0 -1
  335. package/dist/apps/platform/App.js.map +0 -1
  336. package/dist/apps/platform/index.d.ts +0 -2
  337. package/dist/apps/platform/index.d.ts.map +0 -1
  338. package/dist/apps/platform/index.js +0 -2
  339. package/dist/apps/platform/index.js.map +0 -1
  340. package/dist/apps/platform/routes/api-keys.d.ts.map +0 -1
  341. package/dist/apps/platform/routes/api-keys.js.map +0 -1
  342. package/dist/apps/platform/routes/invitations.d.ts.map +0 -1
  343. package/dist/apps/platform/routes/invitations.js.map +0 -1
  344. package/dist/apps/platform/routes/me.d.ts.map +0 -1
  345. package/dist/apps/platform/routes/me.js.map +0 -1
  346. package/dist/apps/platform/routes/members.d.ts.map +0 -1
  347. package/dist/apps/platform/routes/members.js.map +0 -1
  348. package/dist/apps/platform/routes/orgs.d.ts.map +0 -1
  349. package/dist/apps/platform/routes/orgs.js.map +0 -1
  350. package/dist/apps/platform/routes/projects.js.map +0 -1
  351. package/src/apps/platform/index.ts +0 -1
  352. package/src/apps/platform/routes/me.test.ts +0 -121
  353. /package/dist/apps/{platform → management}/routes/me.js +0 -0
  354. /package/dist/apps/{platform → management}/routes/members.d.ts +0 -0
  355. /package/dist/apps/{platform → management}/routes/members.js +0 -0
  356. /package/dist/apps/{platform → management}/routes/projects.js +0 -0
  357. /package/src/apps/{platform → management}/routes/me.ts +0 -0
  358. /package/src/apps/{platform → management}/routes/members.test.ts +0 -0
  359. /package/src/apps/{platform → management}/routes/members.ts +0 -0
  360. /package/src/apps/{platform → management}/routes/orgs.test.ts +0 -0
  361. /package/src/apps/{platform → management}/routes/projects.test.ts +0 -0
  362. /package/src/apps/{platform → management}/routes/projects.ts +0 -0
@@ -6,6 +6,7 @@ import type * as App from '../../../App.js'
6
6
  import * as Auth from '../../../internal/Auth.js'
7
7
  import * as Cache from '../../../internal/Cache.js'
8
8
  import * as Cursor from '../../../internal/Cursor.js'
9
+ import * as Fees from '../../../internal/Fees.js'
9
10
  import * as OpenApi from '../../../internal/OpenApi.js'
10
11
  import * as Response from '../../../internal/Response.js'
11
12
  import * as Schema from '../../../internal/Schema.js'
@@ -25,13 +26,6 @@ import { decodeTransactionType, embedFeeTokens, schema as txSchema } from './tra
25
26
  /** Example transaction hash surfaced in OpenAPI docs. */
26
27
  const exampleHash = '0x515801d7f9a5ac705e793e85904c9c69b3f1694b465cc8fb6ba3f0298dc82665'
27
28
 
28
- // Tempo gas prices are denominated in attodollars (10^-18 USD) while fee-token
29
- // balances use 6 decimals (microdollars, 10^-6 USD), so the fee charged to the
30
- // fee payer — in the fee token's base units — is
31
- // `ceil(gasUsed * effectiveGasPrice / 10^12)` (ceiling division). Mirrors
32
- // `calc_gas_balance_spending` in tempoxyz/tempo.
33
- const feeScalingFactor = 10n ** 12n
34
-
35
29
  /**
36
30
  * Computes the fee charged to the fee payer, in the fee token's base units, from
37
31
  * the receipt's `gasUsed` and decimal `effectiveGasPrice`. Returns undefined
@@ -39,8 +33,7 @@ const feeScalingFactor = 10n ** 12n
39
33
  */
40
34
  function computeFeeAmount(gasUsed: number | undefined, effectiveGasPrice: string | undefined) {
41
35
  if (gasUsed === undefined || effectiveGasPrice === undefined) return undefined
42
- const product = BigInt(gasUsed) * BigInt(effectiveGasPrice)
43
- return ((product + feeScalingFactor - 1n) / feeScalingFactor).toString()
36
+ return Fees.fromGas(BigInt(gasUsed), BigInt(effectiveGasPrice)).toString()
44
37
  }
45
38
 
46
39
  /** Zod schemas owned by the receipt handlers. */
@@ -96,7 +96,7 @@ describe('POST /rpc', () => {
96
96
  }
97
97
  })
98
98
 
99
- test('routes anonymous requests to the public RPC without basic auth', async () => {
99
+ test('allows eth-prefixed methods anonymously', async () => {
100
100
  const fetch = mockRpc()
101
101
 
102
102
  try {
@@ -109,7 +109,7 @@ describe('POST /rpc', () => {
109
109
 
110
110
  const response = await app.fetch(
111
111
  new Request('http://tempo-api.test/rpc/testnet', {
112
- body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'eth_chainId' }),
112
+ body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'eth_fillTransaction' }),
113
113
  method: 'POST',
114
114
  }),
115
115
  )
@@ -122,6 +122,82 @@ describe('POST /rpc', () => {
122
122
  }
123
123
  })
124
124
 
125
+ test('requires an API key for non-eth methods', async () => {
126
+ const fetch = mockRpc()
127
+
128
+ try {
129
+ const app = TestApp.create()
130
+ const response = await app.fetch(
131
+ new Request('http://tempo-api.test/rpc', {
132
+ body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'tempo_fundAddress' }),
133
+ method: 'POST',
134
+ }),
135
+ )
136
+ const body = (await response.json()) as Record<string, unknown>
137
+ const { requestId, ...stable } = body
138
+
139
+ expect(response.status).toMatchInlineSnapshot(`401`)
140
+ expect(typeof requestId).toMatchInlineSnapshot(`"string"`)
141
+ expect(stable).toMatchInlineSnapshot(`
142
+ {
143
+ "error": {
144
+ "code": "api_key_missing",
145
+ "message": "Missing API key",
146
+ },
147
+ }
148
+ `)
149
+ expect(fetch.calls).toMatchInlineSnapshot(`[]`)
150
+ } finally {
151
+ fetch.restore()
152
+ }
153
+ })
154
+
155
+ test('requires an API key when a batch includes a private method', async () => {
156
+ const fetch = mockRpc()
157
+
158
+ try {
159
+ const app = TestApp.create()
160
+ const response = await app.fetch(
161
+ new Request('http://tempo-api.test/rpc', {
162
+ body: JSON.stringify([
163
+ { id: 1, jsonrpc: '2.0', method: 'eth_chainId' },
164
+ { id: 2, jsonrpc: '2.0', method: 'tempo_fundAddress' },
165
+ ]),
166
+ method: 'POST',
167
+ }),
168
+ )
169
+ const body = (await response.json()) as { error?: { code?: unknown } }
170
+
171
+ expect(response.status).toMatchInlineSnapshot(`401`)
172
+ expect(body.error?.code).toMatchInlineSnapshot(`"api_key_missing"`)
173
+ expect(fetch.calls).toMatchInlineSnapshot(`[]`)
174
+ } finally {
175
+ fetch.restore()
176
+ }
177
+ })
178
+
179
+ test('allows API keys to call private methods', async () => {
180
+ const fetch = mockRpc()
181
+
182
+ try {
183
+ const app = TestApp.create()
184
+ const response = await app.fetch(
185
+ new Request('http://tempo-api.test/rpc', {
186
+ body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'tempo_fundAddress' }),
187
+ headers: { 'tempo-api-key': TestApp.key.token },
188
+ method: 'POST',
189
+ }),
190
+ )
191
+
192
+ expect(response.status).toMatchInlineSnapshot(`200`)
193
+ expect(fetch.calls[0]?.body).toMatchInlineSnapshot(
194
+ `"{"id":1,"jsonrpc":"2.0","method":"tempo_fundAddress"}"`,
195
+ )
196
+ } finally {
197
+ fetch.restore()
198
+ }
199
+ })
200
+
125
201
  test('uses the requested chain id for upstream URL resolution', async () => {
126
202
  const fetch = mockRpc()
127
203
 
@@ -143,9 +143,22 @@ export function rpc() {
143
143
  summary: 'Call JSON-RPC',
144
144
  tags: ['RPC'],
145
145
  }),
146
- (c) => {
146
+ async (c) => {
147
147
  if (Auth.narrowAccess) return Auth.accessError(c)
148
148
 
149
+ if (requiresApiKey(c)) {
150
+ const body = await c.req.raw
151
+ .clone()
152
+ .json()
153
+ .catch(() => undefined)
154
+ if (!isPublicRequest(body))
155
+ return Response.error(c, {
156
+ code: 'api_key_missing',
157
+ message: 'Missing API key',
158
+ status: 401,
159
+ })
160
+ }
161
+
149
162
  const chainId = resolveChainId(c)
150
163
  if (!chainId)
151
164
  return Response.error(c, {
@@ -161,6 +174,23 @@ export function rpc() {
161
174
  )
162
175
  }
163
176
 
177
+ function requiresApiKey(c: Context<App.Environment>) {
178
+ if (!c.get('auth')) return false
179
+ const principal = Auth.getPrincipal(c)
180
+ return principal?.type !== 'api_key' && principal?.type !== 'super_admin'
181
+ }
182
+
183
+ function isPublicRequest(body: unknown): boolean {
184
+ const requests = Array.isArray(body) ? body : [body]
185
+ return requests.length > 0 && requests.every((request) => isPublicMethod(request))
186
+ }
187
+
188
+ function isPublicMethod(request: unknown): boolean {
189
+ if (!request || typeof request !== 'object') return false
190
+ const method = (request as Record<string, unknown>)['method']
191
+ return typeof method === 'string' && method.startsWith('eth_')
192
+ }
193
+
164
194
  async function passthrough(
165
195
  c: Context<App.Environment>,
166
196
  chainId: z.output<typeof Schema.ChainId>,
@@ -1151,7 +1151,7 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
1151
1151
  // the real keyset/`toBlock` SQL and decode path end to end — no fabricated rows.
1152
1152
  const realTidx = Tidx.getClient({
1153
1153
  chainId: 42431,
1154
- tidx: { baseUrl: 'https://tidx.tempo.xyz', basicAuth: process.env.VITE_TIDX_BASIC_AUTH },
1154
+ tidx: { baseUrl: 'https://tidx.tempo.xyz', basicAuth: process.env.TIDX_BASIC_AUTH },
1155
1155
  })
1156
1156
  // The monitoring scanners (`log:emitted`/`block:created`/`transaction:included`)
1157
1157
  // read the same immutable historical window over real RPC (chain 42431 →
@@ -533,7 +533,7 @@ export namespace schema {
533
533
  .string()
534
534
  .check(
535
535
  z.describe('Webhook subscription ID (`wh_…`).'),
536
- z.meta({ examples: ['wh_abc123'] }),
536
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
537
537
  ),
538
538
  lastDeliveryAt: z
539
539
  .optional(z.iso.datetime())
@@ -594,7 +594,10 @@ export namespace schema {
594
594
  ),
595
595
  id: z
596
596
  .string()
597
- .check(z.describe('Webhook delivery ID (`whd_…`).'), z.meta({ examples: ['whd_abc123'] })),
597
+ .check(
598
+ z.describe('Webhook delivery ID (`whd_…`).'),
599
+ z.meta({ examples: ['whd_001718668800000_C1yJkk7CuML98HFthEDk9PsY'] }),
600
+ ),
598
601
  requestUrl: z
599
602
  .string()
600
603
  .check(
@@ -620,7 +623,7 @@ export namespace schema {
620
623
  .string()
621
624
  .check(
622
625
  z.describe('Subscription ID (`wh_…`) this delivery belongs to.'),
623
- z.meta({ examples: ['wh_abc123'] }),
626
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
624
627
  ),
625
628
  })
626
629
  .check(z.describe('One attempt by Tempo to deliver an event to your webhook URL.'))
@@ -901,7 +904,7 @@ export namespace schema {
901
904
  .string()
902
905
  .check(
903
906
  z.describe('Subscription ID (`wh_…`) that produced this delivery.'),
904
- z.meta({ examples: ['wh_abc123'] }),
907
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
905
908
  ),
906
909
  }
907
910
 
@@ -1075,7 +1078,7 @@ export namespace schema {
1075
1078
  .string()
1076
1079
  .check(
1077
1080
  z.describe('Webhook subscription ID (`wh_…`).'),
1078
- z.meta({ examples: ['wh_001718668800000_V1StGXR8Z5jdHi6B2myTq'] }),
1081
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
1079
1082
  ),
1080
1083
  })
1081
1084
  .check(z.describe('Path parameters for a webhook subscription request.'))
@@ -1158,13 +1161,13 @@ export namespace schema {
1158
1161
  .string()
1159
1162
  .check(
1160
1163
  z.describe('Delivery ID (`whd_…`) you want Tempo to replay.'),
1161
- z.meta({ examples: ['whd_001718668800000_8oQ2pVmZ4kKxWnLcRfTbN'] }),
1164
+ z.meta({ examples: ['whd_001718668800000_C1yJkk7CuML98HFthEDk9PsY'] }),
1162
1165
  ),
1163
1166
  id: z
1164
1167
  .string()
1165
1168
  .check(
1166
1169
  z.describe('Webhook subscription ID (`wh_…`).'),
1167
- z.meta({ examples: ['wh_001718668800000_V1StGXR8Z5jdHi6B2myTq'] }),
1170
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
1168
1171
  ),
1169
1172
  })
1170
1173
  .check(z.describe('Path parameters for retrying a webhook delivery.'))
@@ -1209,7 +1212,7 @@ export namespace schema {
1209
1212
  .string()
1210
1213
  .check(
1211
1214
  z.describe('ID of the webhook subscription that was deleted.'),
1212
- z.meta({ examples: ['wh_abc123'] }),
1215
+ z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
1213
1216
  ),
1214
1217
  })
1215
1218
  .check(z.describe('Confirmation that the webhook subscription was deleted.'))
@@ -1,18 +1,16 @@
1
+ import type { Context } from 'hono'
1
2
  import { Hono } from 'hono'
2
- import { Handler as vocs_Handler } from 'vocs/server'
3
+ import type { Handler as vocs_Handler } from 'vocs/server'
3
4
 
4
5
  import type * as App from '../../App.js'
5
6
  import * as Metadata from '../metadata.js'
6
- import openrpcSpec from '../../openrpc.json' with { type: 'json' }
7
- import { pilatFontFaces } from './fonts.js'
8
- import { logoUrl } from './logo.js'
9
7
 
10
8
  /**
11
9
  * The docs route group: the Vocs API reference served at the app root.
12
10
  *
13
11
  * ```ts
14
12
  * import { docs } from 'tapimo/docs'
15
- * App.create(options).route('/', data()).route('/', platform()).route('/', docs())
13
+ * App.create(options).route('/', data()).route('/', management()).route('/', docs())
16
14
  * ```
17
15
  *
18
16
  * The group registers no routes itself: it carries a reference factory (via
@@ -23,21 +21,26 @@ import { logoUrl } from './logo.js'
23
21
  *
24
22
  * Lives in the `tapimo/docs` subpath (never re-exported from `tapimo/apps`) so
25
23
  * the Vocs renderer and its multi-MB icon/font data are bundled only by
26
- * deployments that actually serve docs.
24
+ * deployments that actually serve docs. Even then the renderer loads lazily on
25
+ * the first docs request (see `reference.ts`), so API traffic and isolate
26
+ * startup never pay for it.
27
27
  */
28
28
  export function docs(options: docs.Options = {}) {
29
29
  return Metadata.attach(new Hono<App.Environment>(), {
30
- docs: ({ spec }) =>
31
- vocs_Handler.openApi(
32
- {
33
- // Inline the OpenRPC doc so vocs expands it without a self-subrequest
34
- // (see `inlineOpenrpc`); the public `/openapi.json` keeps the URL ref.
35
- spec: () => spec().then(inlineOpenrpc),
36
- sidebar: { collapsed: true },
37
- vocs: { logoUrl, title: 'Tempo API Reference', ...options },
38
- },
39
- { css, fallback: 'next' },
40
- ),
30
+ docs: ({ spec }) => {
31
+ // Memoized across requests: all docs traffic shares one handler.
32
+ let handler: Promise<Hono> | undefined
33
+ return new Hono<App.Environment>().get('*', async (c, next) => {
34
+ handler ??= import('./reference.js').then((m) =>
35
+ m.create({ mount: mountFromRoutePath(c.req.routePath), spec, vocs: options }),
36
+ )
37
+ const response = await (await handler).fetch(c.req.raw, c.env, executionCtx(c))
38
+ // Inner 404 means "not a docs route" (`fallback: 'next'` semantics):
39
+ // defer to the host app's later routes / JSON `notFound`.
40
+ if (response.status === 404) return next()
41
+ return response
42
+ })
43
+ },
41
44
  })
42
45
  }
43
46
 
@@ -46,91 +49,17 @@ export declare namespace docs {
46
49
  type Options = NonNullable<Parameters<typeof vocs_Handler.openApi>[0]['vocs']>
47
50
  }
48
51
 
49
- /**
50
- * Custom CSS injected into the standalone reference's shell `<head>` (via
51
- * `Handler.openApi(_, { css })`), after the Vocs design-system styles so it
52
- * overrides them:
53
- *
54
- * - Page/surface backgrounds use Tempo's near-black dark palette and pure-white
55
- * light palette via `light-dark(<light>, <dark>)`.
56
- * - The dark border color is darkened (the light theme keeps its default).
57
- * - Every corner is squared. The universal `!important` rule beats hard-coded
58
- * `border-radius` values and inline styles (e.g. the Scalar playground), which
59
- * overriding the radius scale variables alone would miss.
60
- * - The default sans/body font is Pilat (Vocs reads `--vocs-font-family`); the
61
- * webfont is embedded via {@link pilatFontFaces}. Body stays at the default
62
- * weight (400); headings are pinned to 500, which renders Pilat Demi (the
63
- * family has no 500 cut, so Demi covers the 500-600 range — see
64
- * {@link pilatFontFaces}).
65
- */
66
- const css = `${pilatFontFaces}
67
-
68
- :root {
69
- --vocs-font-family: "Pilat", Arial, Helvetica, sans-serif;
70
- --vocs-background-color-primary: light-dark(#fafafa, #0a0a0a);
71
- --vocs-background-color-surface: light-dark(#fff, #121212);
72
- }
73
-
74
- :is(h1, h2, h3, h4, h5, h6)[data-v] {
75
- font-weight: 500;
76
- }
77
-
78
- /* Nudge the header logo a touch larger than the default max-h-7 (1.75rem). */
79
- [data-v-logo-image] {
80
- max-height: 2rem;
81
- }
82
-
83
- /* Sidebar leaf items render Regular (the nav's 450 default otherwise resolves to
84
- * Demi via the 500-600 range). Group labels ([data-v-sidebar-section-header])
85
- * keep their heavier weight. */
86
- [data-v-sidebar-item] {
87
- font-weight: 400;
52
+ /** Derives the host mount prefix from Hono's matched `routePath` (`/api/*` → `/api`, `/*` → ``). */
53
+ function mountFromRoutePath(routePath: string) {
54
+ return routePath.replace(/\*+$/, '').replace(/\/+$/, '')
88
55
  }
89
56
 
90
- [data-vocs-theme='dark'] {
91
- --vocs-color-gray4: oklch(20% 0 0);
92
- --vocs-color-gray5: oklch(0.23 0 0);
93
- --vocs-border-color-primary: oklch(0.25 0 0);
94
- --vocs-border-color-secondary: oklch(0.25 0 0);
95
- }
96
-
97
- *,
98
- *::before,
99
- *::after {
100
- border-radius: 0 !important;
101
- }`
102
-
103
- /**
104
- * Returns a shallow copy of `spec` with the JSON-RPC passthrough operation's
105
- * `x-openrpc` replaced by the inline OpenRPC document, for the docs handler.
106
- *
107
- * Vocs expands `x-openrpc` at request time. A URL reference (as kept in the
108
- * public `/openapi.json` by `App.create`'s `applyOpenrpcLink`) would make the
109
- * docs worker fetch its own `/openrpc.json` — a self-subrequest that is
110
- * unreliable on Cloudflare Workers and silently falls back to a single,
111
- * unexpanded operation. Inlining the committed artifact keeps expansion
112
- * deterministic across local and deployed environments, without bloating the
113
- * public spec. Only the affected path/op are cloned; the rest of the (large)
114
- * document is shared by reference.
115
- */
116
- function inlineOpenrpc<spec extends { paths: Record<string, unknown> }>(spec: spec): spec {
117
- const paths: Record<string, unknown> = {}
118
- for (const [pathname, item] of Object.entries(spec.paths)) {
119
- let next = item
120
- if (isRecord(item))
121
- for (const [method, op] of Object.entries(item))
122
- if (isRpcOperation(op)) next = { ...item, [method]: { ...op, 'x-openrpc': openrpcSpec } }
123
- paths[pathname] = next
57
+ // `c.executionCtx` throws outside Workers (tests, Node); docs rendering never
58
+ // uses `waitUntil`, so absence is fine.
59
+ function executionCtx(c: Context) {
60
+ try {
61
+ return c.executionCtx
62
+ } catch {
63
+ return undefined
124
64
  }
125
- return { ...spec, paths }
126
- }
127
-
128
- // The JSON-RPC passthrough's operation id, set by its route definition and
129
- // targeted by `App.create`'s `applyOpenrpcLink`.
130
- function isRpcOperation(op: unknown): op is Record<string, unknown> {
131
- return isRecord(op) && op['operationId'] === 'rpcRequest'
132
- }
133
-
134
- function isRecord(value: unknown): value is Record<string, unknown> {
135
- return !!value && typeof value === 'object' && !Array.isArray(value)
136
65
  }
@@ -0,0 +1,132 @@
1
+ import { Hono } from 'hono'
2
+ import { Handler as vocs_Handler } from 'vocs/server'
3
+
4
+ import type * as App from '../../App.js'
5
+ import openrpcSpec from '../../openrpc.json' with { type: 'json' }
6
+ import type { docs } from './App.js'
7
+ import { pilatFontFaces } from './fonts.js'
8
+ import { logoUrl } from './logo.js'
9
+
10
+ /**
11
+ * Builds the Vocs reference handler. Loaded via dynamic import on the first
12
+ * docs request (see `docs()` in `App.ts`), keeping the multi-MB renderer off
13
+ * isolate startup.
14
+ */
15
+ export function create(options: create.Options): Hono {
16
+ const { mount, spec, vocs } = options
17
+ const handler = vocs_Handler.openApi(
18
+ {
19
+ // Inline the OpenRPC doc so vocs expands it without a self-subrequest
20
+ // (see `inlineOpenrpc`); the public `/openapi.json` keeps the URL ref.
21
+ spec: () => spec().then(inlineOpenrpc),
22
+ sidebar: { collapsed: true },
23
+ vocs: { logoUrl, title: 'Tempo API Reference', ...vocs },
24
+ },
25
+ { css, fallback: 'next' },
26
+ )
27
+ if (!mount) return handler
28
+ // Re-mount under the host prefix so the handler's `routePath`-derived mount
29
+ // (asset link bases, known-route checks) matches a direct `.route()` mount.
30
+ return new Hono().route(mount, handler)
31
+ }
32
+
33
+ export declare namespace create {
34
+ /** Options for building the reference handler. */
35
+ type Options = {
36
+ /** Host mount prefix derived from the wrapper's matched `routePath` (`''` at root). */
37
+ mount: string
38
+ /** Memoized OpenAPI document builder — the same document served at `/openapi.json`. */
39
+ spec: App.create.DocsContext['spec']
40
+ /** Vocs reference options (theme, top navigation, logo, socials, …). */
41
+ vocs: docs.Options
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Custom CSS injected into the standalone reference's shell `<head>` (via
47
+ * `Handler.openApi(_, { css })`), after the Vocs design-system styles so it
48
+ * overrides them:
49
+ *
50
+ * - Page/surface backgrounds use Tempo's near-black dark palette and pure-white
51
+ * light palette via `light-dark(<light>, <dark>)`.
52
+ * - The dark border color is darkened (the light theme keeps its default).
53
+ * - Every corner is squared. The universal `!important` rule beats hard-coded
54
+ * `border-radius` values and inline styles (e.g. the Scalar playground), which
55
+ * overriding the radius scale variables alone would miss.
56
+ * - The default sans/body font is Pilat (Vocs reads `--vocs-font-family`); the
57
+ * webfont is embedded via {@link pilatFontFaces}. Body stays at the default
58
+ * weight (400); headings are pinned to 500, which renders Pilat Demi (the
59
+ * family has no 500 cut, so Demi covers the 500-600 range — see
60
+ * {@link pilatFontFaces}).
61
+ */
62
+ const css = `${pilatFontFaces}
63
+
64
+ :root {
65
+ --vocs-font-family: "Pilat", Arial, Helvetica, sans-serif;
66
+ --vocs-background-color-primary: light-dark(#fafafa, #0a0a0a);
67
+ --vocs-background-color-surface: light-dark(#fff, #121212);
68
+ }
69
+
70
+ :is(h1, h2, h3, h4, h5, h6)[data-v] {
71
+ font-weight: 500;
72
+ }
73
+
74
+ /* Nudge the header logo a touch larger than the default max-h-7 (1.75rem). */
75
+ [data-v-logo-image] {
76
+ max-height: 2rem;
77
+ }
78
+
79
+ /* Sidebar leaf items render Regular (the nav's 450 default otherwise resolves to
80
+ * Demi via the 500-600 range). Group labels ([data-v-sidebar-section-header])
81
+ * keep their heavier weight. */
82
+ [data-v-sidebar-item] {
83
+ font-weight: 400;
84
+ }
85
+
86
+ [data-vocs-theme='dark'] {
87
+ --vocs-color-gray4: oklch(20% 0 0);
88
+ --vocs-color-gray5: oklch(0.23 0 0);
89
+ --vocs-border-color-primary: oklch(0.25 0 0);
90
+ --vocs-border-color-secondary: oklch(0.25 0 0);
91
+ }
92
+
93
+ *,
94
+ *::before,
95
+ *::after {
96
+ border-radius: 0 !important;
97
+ }`
98
+
99
+ /**
100
+ * Returns a shallow copy of `spec` with the JSON-RPC passthrough operation's
101
+ * `x-openrpc` replaced by the inline OpenRPC document, for the docs handler.
102
+ *
103
+ * Vocs expands `x-openrpc` at request time. A URL reference (as kept in the
104
+ * public `/openapi.json` by `App.create`'s `applyOpenrpcLink`) would make the
105
+ * docs worker fetch its own `/openrpc.json` — a self-subrequest that is
106
+ * unreliable on Cloudflare Workers and silently falls back to a single,
107
+ * unexpanded operation. Inlining the committed artifact keeps expansion
108
+ * deterministic across local and deployed environments, without bloating the
109
+ * public spec. Only the affected path/op are cloned; the rest of the (large)
110
+ * document is shared by reference.
111
+ */
112
+ function inlineOpenrpc<spec extends { paths: Record<string, unknown> }>(spec: spec): spec {
113
+ const paths: Record<string, unknown> = {}
114
+ for (const [pathname, item] of Object.entries(spec.paths)) {
115
+ let next = item
116
+ if (isRecord(item))
117
+ for (const [method, op] of Object.entries(item))
118
+ if (isRpcOperation(op)) next = { ...item, [method]: { ...op, 'x-openrpc': openrpcSpec } }
119
+ paths[pathname] = next
120
+ }
121
+ return { ...spec, paths }
122
+ }
123
+
124
+ // The JSON-RPC passthrough's operation id, set by its route definition and
125
+ // targeted by `App.create`'s `applyOpenrpcLink`.
126
+ function isRpcOperation(op: unknown): op is Record<string, unknown> {
127
+ return isRecord(op) && op['operationId'] === 'rpcRequest'
128
+ }
129
+
130
+ function isRecord(value: unknown): value is Record<string, unknown> {
131
+ return !!value && typeof value === 'object' && !Array.isArray(value)
132
+ }
package/src/apps/index.ts CHANGED
@@ -1,3 +1,4 @@
1
- export { data } from './data/index.js'
2
- export { platform } from './platform/index.js'
1
+ export { data, FundingRouteProviders } from './data/index.js'
2
+ export { management } from './management/index.js'
3
+ export { mcp } from './mcp.js'
3
4
  export { relay } from './relay/index.js'