@hugomrdias/foxer 0.0.1

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 (311) hide show
  1. package/README.md +56 -0
  2. package/dist/src/api/index.d.ts +2 -0
  3. package/dist/src/api/index.d.ts.map +1 -0
  4. package/dist/src/api/index.js +2 -0
  5. package/dist/src/api/index.js.map +1 -0
  6. package/dist/src/api/runner.d.ts +12 -0
  7. package/dist/src/api/runner.d.ts.map +1 -0
  8. package/dist/src/api/runner.js +29 -0
  9. package/dist/src/api/runner.js.map +1 -0
  10. package/dist/src/api/server.d.ts +18 -0
  11. package/dist/src/api/server.d.ts.map +1 -0
  12. package/dist/src/api/server.js +21 -0
  13. package/dist/src/api/server.js.map +1 -0
  14. package/dist/src/api/sql-middleware.d.ts +7 -0
  15. package/dist/src/api/sql-middleware.d.ts.map +1 -0
  16. package/dist/src/api/sql-middleware.js +95 -0
  17. package/dist/src/api/sql-middleware.js.map +1 -0
  18. package/dist/src/api/sql.d.ts +14 -0
  19. package/dist/src/api/sql.d.ts.map +1 -0
  20. package/dist/src/api/sql.js +108 -0
  21. package/dist/src/api/sql.js.map +1 -0
  22. package/dist/src/api/sse.d.ts +3 -0
  23. package/dist/src/api/sse.d.ts.map +1 -0
  24. package/dist/src/api/sse.js +11 -0
  25. package/dist/src/api/sse.js.map +1 -0
  26. package/dist/src/bin/dev.d.ts +3 -0
  27. package/dist/src/bin/dev.d.ts.map +1 -0
  28. package/dist/src/bin/dev.js +76 -0
  29. package/dist/src/bin/dev.js.map +1 -0
  30. package/dist/src/bin/flags.d.ts +32 -0
  31. package/dist/src/bin/flags.d.ts.map +1 -0
  32. package/dist/src/bin/flags.js +55 -0
  33. package/dist/src/bin/flags.js.map +1 -0
  34. package/dist/src/bin/index.d.ts +3 -0
  35. package/dist/src/bin/index.d.ts.map +1 -0
  36. package/dist/src/bin/index.js +22 -0
  37. package/dist/src/bin/index.js.map +1 -0
  38. package/dist/src/bin/utils.d.ts +4 -0
  39. package/dist/src/bin/utils.d.ts.map +1 -0
  40. package/dist/src/bin/utils.js +52 -0
  41. package/dist/src/bin/utils.js.map +1 -0
  42. package/dist/src/client/index.d.ts +18 -0
  43. package/dist/src/client/index.d.ts.map +1 -0
  44. package/dist/src/client/index.js +150 -0
  45. package/dist/src/client/index.js.map +1 -0
  46. package/dist/src/config/config.d.ts +157 -0
  47. package/dist/src/config/config.d.ts.map +1 -0
  48. package/dist/src/config/config.js +65 -0
  49. package/dist/src/config/config.js.map +1 -0
  50. package/dist/src/config/env.d.ts +25 -0
  51. package/dist/src/config/env.d.ts.map +1 -0
  52. package/dist/src/config/env.js +21 -0
  53. package/dist/src/config/env.js.map +1 -0
  54. package/dist/src/contants.d.ts +4 -0
  55. package/dist/src/contants.d.ts.map +1 -0
  56. package/dist/src/contants.js +4 -0
  57. package/dist/src/contants.js.map +1 -0
  58. package/dist/src/db/actions/blocks.d.ts +44 -0
  59. package/dist/src/db/actions/blocks.d.ts.map +1 -0
  60. package/dist/src/db/actions/blocks.js +152 -0
  61. package/dist/src/db/actions/blocks.js.map +1 -0
  62. package/dist/src/db/actions/index.d.ts +2 -0
  63. package/dist/src/db/actions/index.d.ts.map +1 -0
  64. package/dist/src/db/actions/index.js +2 -0
  65. package/dist/src/db/actions/index.js.map +1 -0
  66. package/dist/src/db/actions/transactions.d.ts +11 -0
  67. package/dist/src/db/actions/transactions.d.ts.map +1 -0
  68. package/dist/src/db/actions/transactions.js +22 -0
  69. package/dist/src/db/actions/transactions.js.map +1 -0
  70. package/dist/src/db/client.d.ts +329 -0
  71. package/dist/src/db/client.d.ts.map +1 -0
  72. package/dist/src/db/client.js +108 -0
  73. package/dist/src/db/client.js.map +1 -0
  74. package/dist/src/db/column-types.d.ts +132 -0
  75. package/dist/src/db/column-types.d.ts.map +1 -0
  76. package/dist/src/db/column-types.js +86 -0
  77. package/dist/src/db/column-types.js.map +1 -0
  78. package/dist/src/db/encode.d.ts +10 -0
  79. package/dist/src/db/encode.d.ts.map +1 -0
  80. package/dist/src/db/encode.js +79 -0
  81. package/dist/src/db/encode.js.map +1 -0
  82. package/dist/src/db/migrate.d.ts +31 -0
  83. package/dist/src/db/migrate.d.ts.map +1 -0
  84. package/dist/src/db/migrate.js +147 -0
  85. package/dist/src/db/migrate.js.map +1 -0
  86. package/dist/src/db/schema/blocks.d.ts +369 -0
  87. package/dist/src/db/schema/blocks.d.ts.map +1 -0
  88. package/dist/src/db/schema/blocks.js +24 -0
  89. package/dist/src/db/schema/blocks.js.map +1 -0
  90. package/dist/src/db/schema/index.d.ts +1415 -0
  91. package/dist/src/db/schema/index.d.ts.map +1 -0
  92. package/dist/src/db/schema/index.js +18 -0
  93. package/dist/src/db/schema/index.js.map +1 -0
  94. package/dist/src/db/schema/transactions.d.ts +336 -0
  95. package/dist/src/db/schema/transactions.d.ts.map +1 -0
  96. package/dist/src/db/schema/transactions.js +33 -0
  97. package/dist/src/db/schema/transactions.js.map +1 -0
  98. package/dist/src/db/transaction.d.ts +7 -0
  99. package/dist/src/db/transaction.d.ts.map +1 -0
  100. package/dist/src/db/transaction.js +8 -0
  101. package/dist/src/db/transaction.js.map +1 -0
  102. package/dist/src/hooks/default-hooks.d.ts +2 -0
  103. package/dist/src/hooks/default-hooks.d.ts.map +1 -0
  104. package/dist/src/hooks/default-hooks.js +107 -0
  105. package/dist/src/hooks/default-hooks.js.map +1 -0
  106. package/dist/src/hooks/registry.d.ts +51 -0
  107. package/dist/src/hooks/registry.d.ts.map +1 -0
  108. package/dist/src/hooks/registry.js +32 -0
  109. package/dist/src/hooks/registry.js.map +1 -0
  110. package/dist/src/index.d.ts +10 -0
  111. package/dist/src/index.d.ts.map +1 -0
  112. package/dist/src/index.js +4 -0
  113. package/dist/src/index.js.map +1 -0
  114. package/dist/src/indexer/backfill.d.ts +15 -0
  115. package/dist/src/indexer/backfill.d.ts.map +1 -0
  116. package/dist/src/indexer/backfill.js +95 -0
  117. package/dist/src/indexer/backfill.js.map +1 -0
  118. package/dist/src/indexer/live.d.ts +20 -0
  119. package/dist/src/indexer/live.d.ts.map +1 -0
  120. package/dist/src/indexer/live.js +51 -0
  121. package/dist/src/indexer/live.js.map +1 -0
  122. package/dist/src/indexer/process-block.d.ts +29 -0
  123. package/dist/src/indexer/process-block.d.ts.map +1 -0
  124. package/dist/src/indexer/process-block.js +91 -0
  125. package/dist/src/indexer/process-block.js.map +1 -0
  126. package/dist/src/indexer/queue-block.d.ts +18 -0
  127. package/dist/src/indexer/queue-block.d.ts.map +1 -0
  128. package/dist/src/indexer/queue-block.js +38 -0
  129. package/dist/src/indexer/queue-block.js.map +1 -0
  130. package/dist/src/indexer/reorg.d.ts +24 -0
  131. package/dist/src/indexer/reorg.d.ts.map +1 -0
  132. package/dist/src/indexer/reorg.js +83 -0
  133. package/dist/src/indexer/reorg.js.map +1 -0
  134. package/dist/src/indexer/runner.d.ts +14 -0
  135. package/dist/src/indexer/runner.d.ts.map +1 -0
  136. package/dist/src/indexer/runner.js +22 -0
  137. package/dist/src/indexer/runner.js.map +1 -0
  138. package/dist/src/rpc/client.d.ts +11 -0
  139. package/dist/src/rpc/client.d.ts.map +1 -0
  140. package/dist/src/rpc/client.js +18 -0
  141. package/dist/src/rpc/client.js.map +1 -0
  142. package/dist/src/rpc/get-block.d.ts +16 -0
  143. package/dist/src/rpc/get-block.d.ts.map +1 -0
  144. package/dist/src/rpc/get-block.js +77 -0
  145. package/dist/src/rpc/get-block.js.map +1 -0
  146. package/dist/src/rpc/get-logs.d.ts +11 -0
  147. package/dist/src/rpc/get-logs.d.ts.map +1 -0
  148. package/dist/src/rpc/get-logs.js +23 -0
  149. package/dist/src/rpc/get-logs.js.map +1 -0
  150. package/dist/src/schema.d.ts +3 -0
  151. package/dist/src/schema.d.ts.map +1 -0
  152. package/dist/src/schema.js +9 -0
  153. package/dist/src/schema.js.map +1 -0
  154. package/dist/src/types.d.ts +22 -0
  155. package/dist/src/types.d.ts.map +1 -0
  156. package/dist/src/types.js +1 -0
  157. package/dist/src/types.js.map +1 -0
  158. package/dist/src/utils/bloom.d.ts +6 -0
  159. package/dist/src/utils/bloom.d.ts.map +1 -0
  160. package/dist/src/utils/bloom.js +30 -0
  161. package/dist/src/utils/bloom.js.map +1 -0
  162. package/dist/src/utils/build-conflict-columns.d.ts +4 -0
  163. package/dist/src/utils/build-conflict-columns.d.ts.map +1 -0
  164. package/dist/src/utils/build-conflict-columns.js +14 -0
  165. package/dist/src/utils/build-conflict-columns.js.map +1 -0
  166. package/dist/src/utils/common.d.ts +2 -0
  167. package/dist/src/utils/common.d.ts.map +1 -0
  168. package/dist/src/utils/common.js +4 -0
  169. package/dist/src/utils/common.js.map +1 -0
  170. package/dist/src/utils/cursor.d.ts +5 -0
  171. package/dist/src/utils/cursor.d.ts.map +1 -0
  172. package/dist/src/utils/cursor.js +8 -0
  173. package/dist/src/utils/cursor.js.map +1 -0
  174. package/dist/src/utils/format.d.ts +2 -0
  175. package/dist/src/utils/format.d.ts.map +1 -0
  176. package/dist/src/utils/format.js +16 -0
  177. package/dist/src/utils/format.js.map +1 -0
  178. package/dist/src/utils/hash.d.ts +9 -0
  179. package/dist/src/utils/hash.d.ts.map +1 -0
  180. package/dist/src/utils/hash.js +15 -0
  181. package/dist/src/utils/hash.js.map +1 -0
  182. package/dist/src/utils/json.d.ts +5 -0
  183. package/dist/src/utils/json.d.ts.map +1 -0
  184. package/dist/src/utils/json.js +11 -0
  185. package/dist/src/utils/json.js.map +1 -0
  186. package/dist/src/utils/logger.d.ts +11 -0
  187. package/dist/src/utils/logger.d.ts.map +1 -0
  188. package/dist/src/utils/logger.js +111 -0
  189. package/dist/src/utils/logger.js.map +1 -0
  190. package/dist/src/utils/shutdown.d.ts +9 -0
  191. package/dist/src/utils/shutdown.d.ts.map +1 -0
  192. package/dist/src/utils/shutdown.js +24 -0
  193. package/dist/src/utils/shutdown.js.map +1 -0
  194. package/dist/src/utils/timer.d.ts +6 -0
  195. package/dist/src/utils/timer.d.ts.map +1 -0
  196. package/dist/src/utils/timer.js +9 -0
  197. package/dist/src/utils/timer.js.map +1 -0
  198. package/dist/src/utils/types.d.ts +39 -0
  199. package/dist/src/utils/types.d.ts.map +1 -0
  200. package/dist/src/utils/types.js +1 -0
  201. package/dist/src/utils/types.js.map +1 -0
  202. package/dist/tsconfig.tsbuildinfo +1 -0
  203. package/hello/apps/foc-api/README.md +69 -0
  204. package/hello/apps/foc-api/biome.json +8 -0
  205. package/hello/apps/foc-api/index.html +13 -0
  206. package/hello/apps/foc-api/package.json +39 -0
  207. package/hello/apps/foc-api/public/vite.svg +1 -0
  208. package/hello/apps/foc-api/src/app.css +45 -0
  209. package/hello/apps/foc-api/src/app.tsx +43 -0
  210. package/hello/apps/foc-api/src/assets/Cloudflare_Logo.svg +51 -0
  211. package/hello/apps/foc-api/src/assets/react.svg +1 -0
  212. package/hello/apps/foc-api/src/client.ts +41 -0
  213. package/hello/apps/foc-api/src/components/account.tsx +100 -0
  214. package/hello/apps/foc-api/src/components/wallet-options.tsx +43 -0
  215. package/hello/apps/foc-api/src/index.css +68 -0
  216. package/hello/apps/foc-api/src/main.tsx +38 -0
  217. package/hello/apps/foc-api/src/vite-env.d.ts +1 -0
  218. package/hello/apps/foc-api/tsconfig.app.json +44 -0
  219. package/hello/apps/foc-api/tsconfig.json +17 -0
  220. package/hello/apps/foc-api/tsconfig.node.json +25 -0
  221. package/hello/apps/foc-api/tsconfig.worker.json +8 -0
  222. package/hello/apps/foc-api/vite.config.ts +8 -0
  223. package/hello/apps/foc-api/worker/capabilities.ts +25 -0
  224. package/hello/apps/foc-api/worker/index.ts +64 -0
  225. package/hello/apps/foc-api/worker/router.ts +35 -0
  226. package/hello/apps/foc-api/worker-configuration.d.ts +7357 -0
  227. package/hello/apps/foc-api/wrangler.jsonc +50 -0
  228. package/hello/apps/foc-app/README.md +69 -0
  229. package/hello/apps/foc-app/biome.json +8 -0
  230. package/hello/apps/foc-app/index.html +13 -0
  231. package/hello/apps/foc-app/package.json +39 -0
  232. package/hello/apps/foc-app/public/vite.svg +1 -0
  233. package/hello/apps/foc-app/src/app.css +45 -0
  234. package/hello/apps/foc-app/src/app.tsx +43 -0
  235. package/hello/apps/foc-app/src/assets/Cloudflare_Logo.svg +51 -0
  236. package/hello/apps/foc-app/src/assets/react.svg +1 -0
  237. package/hello/apps/foc-app/src/client.ts +41 -0
  238. package/hello/apps/foc-app/src/components/account.tsx +100 -0
  239. package/hello/apps/foc-app/src/components/wallet-options.tsx +43 -0
  240. package/hello/apps/foc-app/src/index.css +68 -0
  241. package/hello/apps/foc-app/src/main.tsx +38 -0
  242. package/hello/apps/foc-app/src/vite-env.d.ts +1 -0
  243. package/hello/apps/foc-app/tsconfig.app.json +44 -0
  244. package/hello/apps/foc-app/tsconfig.json +17 -0
  245. package/hello/apps/foc-app/tsconfig.node.json +25 -0
  246. package/hello/apps/foc-app/tsconfig.worker.json +8 -0
  247. package/hello/apps/foc-app/vite.config.ts +8 -0
  248. package/hello/apps/foc-app/worker/capabilities.ts +25 -0
  249. package/hello/apps/foc-app/worker/index.ts +64 -0
  250. package/hello/apps/foc-app/worker/router.ts +35 -0
  251. package/hello/apps/foc-app/worker-configuration.d.ts +7357 -0
  252. package/hello/apps/foc-app/wrangler.jsonc +50 -0
  253. package/hello/biome.json +50 -0
  254. package/hello/package.json +22 -0
  255. package/hello/pnpm-workspace.yaml +3 -0
  256. package/hello/tsconfig.json +37 -0
  257. package/package.json +78 -0
  258. package/src/api/index.ts +1 -0
  259. package/src/api/runner.ts +43 -0
  260. package/src/api/server.ts +38 -0
  261. package/src/api/sql-middleware.ts +131 -0
  262. package/src/api/sql.ts +149 -0
  263. package/src/api/sse.ts +12 -0
  264. package/src/bin/create.ts +199 -0
  265. package/src/bin/dev.ts +91 -0
  266. package/src/bin/flags.ts +65 -0
  267. package/src/bin/index.ts +28 -0
  268. package/src/bin/utils.ts +55 -0
  269. package/src/config/config.ts +221 -0
  270. package/src/config/env.ts +28 -0
  271. package/src/contants.ts +3 -0
  272. package/src/db/actions/blocks.ts +209 -0
  273. package/src/db/actions/index.ts +1 -0
  274. package/src/db/actions/transactions.ts +32 -0
  275. package/src/db/client.ts +186 -0
  276. package/src/db/column-types.ts +105 -0
  277. package/src/db/encode.ts +99 -0
  278. package/src/db/migrate.ts +222 -0
  279. package/src/db/schema/blocks.ts +24 -0
  280. package/src/db/schema/index.ts +21 -0
  281. package/src/db/schema/transactions.ts +39 -0
  282. package/src/db/transaction.ts +20 -0
  283. package/src/hooks/registry.ts +107 -0
  284. package/src/index.ts +9 -0
  285. package/src/indexer/backfill.ts +133 -0
  286. package/src/indexer/live.ts +76 -0
  287. package/src/indexer/process-block.ts +142 -0
  288. package/src/indexer/queue-block.ts +74 -0
  289. package/src/indexer/reorg.ts +120 -0
  290. package/src/indexer/runner.ts +35 -0
  291. package/src/rpc/client.ts +27 -0
  292. package/src/rpc/get-block.ts +100 -0
  293. package/src/rpc/get-logs.ts +38 -0
  294. package/src/schema.ts +10 -0
  295. package/src/types.ts +32 -0
  296. package/src/utils/bloom.ts +41 -0
  297. package/src/utils/build-conflict-columns.ts +26 -0
  298. package/src/utils/common.ts +3 -0
  299. package/src/utils/cursor.ts +7 -0
  300. package/src/utils/format.ts +18 -0
  301. package/src/utils/hash.ts +17 -0
  302. package/src/utils/json.ts +11 -0
  303. package/src/utils/logger.ts +149 -0
  304. package/src/utils/shutdown.ts +36 -0
  305. package/src/utils/timer.ts +8 -0
  306. package/src/utils/types.ts +87 -0
  307. package/template/biome.json +50 -0
  308. package/template/package.json +22 -0
  309. package/template/pnpm-workspace.yaml +3 -0
  310. package/template/tsconfig.json +37 -0
  311. package/tsconfig.json +8 -0
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Normalizes hash strings so comparisons are case-insensitive.
3
+ */
4
+ export function normalizeHash(hash: string): string {
5
+ return hash.toLowerCase()
6
+ }
7
+
8
+ /**
9
+ * Compares two optional hash strings for equality.
10
+ */
11
+ export function hashEquals(
12
+ left: string | null | undefined,
13
+ right: string | null | undefined
14
+ ): boolean {
15
+ if (left == null || right == null) return left === right
16
+ return normalizeHash(left) === normalizeHash(right)
17
+ }
@@ -0,0 +1,11 @@
1
+ /** biome-ignore-all lint/suspicious/noExplicitAny: its ok */
2
+ type Reviver = (key: string, value: any) => any
3
+
4
+ export function deserialize<type>(value: string, reviver?: Reviver): type {
5
+ return JSON.parse(value, (key, value_) => {
6
+ let value = value_
7
+ if (value?.__type === 'bigint') value = BigInt(value.value)
8
+ if (value?.__type === 'Map') value = new Map(value.value)
9
+ return reviver?.(key, value) ?? value
10
+ })
11
+ }
@@ -0,0 +1,149 @@
1
+ import pc from 'picocolors'
2
+ import type { DestinationStream, LevelWithSilent } from 'pino'
3
+ import pino from 'pino'
4
+ import type { Simplify } from 'type-fest'
5
+ import { stringify } from 'viem'
6
+ import { formatLogDuration } from './format.ts'
7
+
8
+ export type LogMode = 'pretty' | 'json'
9
+ export type LogLevel = Simplify<LevelWithSilent>
10
+ export type Logger = ReturnType<typeof createLogger>
11
+
12
+ export function createLogger({
13
+ level,
14
+ mode,
15
+ }: {
16
+ level: LogLevel
17
+ mode: LogMode
18
+ }) {
19
+ const stream: DestinationStream = {
20
+ write(logString: string) {
21
+ const log = JSON.parse(logString) as Log
22
+ const prettyLog = format(log)
23
+ // biome-ignore lint/suspicious/noConsole: logging to console
24
+ console.log(prettyLog)
25
+ },
26
+ }
27
+ const errorSerializer = pino.stdSerializers.wrapErrorSerializer((error) => {
28
+ error.meta = Array.isArray(error.meta) ? error.meta.join('\n') : error.meta
29
+ // @ts-expect-error - type is not defined in the error serializer
30
+ error.type = undefined
31
+ return error
32
+ })
33
+ let logger: pino.Logger
34
+
35
+ if (mode === 'pretty') {
36
+ logger = pino(
37
+ {
38
+ level,
39
+ serializers: {
40
+ error: errorSerializer,
41
+ },
42
+ // Removes "pid" and "hostname" properties from the log.
43
+ base: undefined,
44
+ },
45
+ stream
46
+ )
47
+ } else {
48
+ logger = pino({
49
+ level,
50
+ serializers: {
51
+ error: errorSerializer,
52
+ },
53
+ // Removes "pid" and "hostname" properties from the log.
54
+ base: undefined,
55
+ })
56
+ }
57
+ return logger
58
+ }
59
+
60
+ type Log = {
61
+ // Pino properties
62
+ level: 50 | 40 | 30 | 20 | 10
63
+ time: number
64
+
65
+ msg: string
66
+
67
+ duration?: number
68
+ error?: Error
69
+ } & Record<string, unknown>
70
+
71
+ const INTERNAL_KEYS = ['level', 'time', 'msg', 'duration', 'error']
72
+
73
+ const levels = {
74
+ 50: { label: 'ERROR', colorLabel: pc.red('ERROR') },
75
+ 40: { label: 'WARN ', colorLabel: pc.yellow('WARN ') },
76
+ 30: { label: 'INFO ', colorLabel: pc.green('INFO ') },
77
+ 20: { label: 'DEBUG', colorLabel: pc.blue('DEBUG') },
78
+ 10: { label: 'TRACE', colorLabel: pc.gray('TRACE') },
79
+ } as const
80
+
81
+ const timeFormatter = new Intl.DateTimeFormat(undefined, {
82
+ hour: '2-digit',
83
+ minute: '2-digit',
84
+ second: '2-digit',
85
+ fractionalSecondDigits: 3,
86
+ hour12: false,
87
+ })
88
+
89
+ const format = (log: Log) => {
90
+ const time = timeFormatter.format(new Date(log.time))
91
+ const levelObject = levels[log.level ?? 30]
92
+
93
+ let prettyLog: string[]
94
+ if (pc.isColorSupported) {
95
+ const level = levelObject.colorLabel
96
+ const messageText = pc.reset(log.msg)
97
+
98
+ let keyText = ''
99
+
100
+ for (const key of Object.keys(log)) {
101
+ if (INTERNAL_KEYS.includes(key)) continue
102
+ const value =
103
+ typeof log[key] === 'string' ? log[key] : stringify(log[key])
104
+ keyText += ` ${key}=${value}`
105
+ }
106
+
107
+ let durationText = ''
108
+ if (log.duration) {
109
+ durationText = ` ${pc.gray(`(${formatLogDuration(log.duration)})`)}`
110
+ }
111
+
112
+ prettyLog = [
113
+ `${pc.dim(time)} ${level} ${messageText}${pc.dim(keyText)}${durationText}`,
114
+ ]
115
+ } else {
116
+ const level = levelObject.label
117
+
118
+ let keyText = ''
119
+ for (const key of Object.keys(log)) {
120
+ if (INTERNAL_KEYS.includes(key)) continue
121
+ const value =
122
+ typeof log[key] === 'string' ? log[key] : stringify(log[key])
123
+ keyText += ` ${key}=${value}`
124
+ }
125
+
126
+ let durationText = ''
127
+ if (log.duration) {
128
+ durationText = ` (${formatLogDuration(log.duration)})`
129
+ }
130
+
131
+ prettyLog = [`${time} ${level} ${log.msg}${keyText}${durationText}`]
132
+ }
133
+
134
+ if (log.error) {
135
+ if (log.error.stack) {
136
+ prettyLog.push(log.error.stack)
137
+ } else {
138
+ prettyLog.push(`${log.error.name}: ${log.error.message}`)
139
+ }
140
+
141
+ if (typeof log.error === 'object' && 'where' in log.error) {
142
+ prettyLog.push(`where: ${log.error.where as string}`)
143
+ }
144
+ if (typeof log.error === 'object' && 'meta' in log.error) {
145
+ prettyLog.push(log.error.meta as string)
146
+ }
147
+ }
148
+ return prettyLog.join('\n')
149
+ }
@@ -0,0 +1,36 @@
1
+ import { asyncExitHook, gracefulExit } from 'exit-hook'
2
+ import type { Logger } from 'pino'
3
+
4
+ export function createExit({
5
+ logger,
6
+ stop,
7
+ }: {
8
+ logger: Logger
9
+ stop: () => Promise<void>
10
+ }) {
11
+ asyncExitHook(
12
+ async () => {
13
+ logger.warn('shutting down...')
14
+ await stop()
15
+ logger.info('shutdown complete')
16
+ process.exit(0)
17
+ },
18
+ {
19
+ wait: 300,
20
+ }
21
+ )
22
+ }
23
+
24
+ export function registerUnhandled({ logger }: { logger: Logger }) {
25
+ process.on('uncaughtException', (error, origin) => {
26
+ if (!origin || origin === 'uncaughtException') {
27
+ logger.error({ error }, 'uncaught exception')
28
+ gracefulExit(1)
29
+ }
30
+ })
31
+
32
+ process.on('unhandledRejection', (error) => {
33
+ logger.error({ error }, 'unhandled rejection')
34
+ gracefulExit(1)
35
+ })
36
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Measures the elapsed wall clock time in milliseconds (ms) between two points.
3
+ * @returns A function returning the elapsed time in milliseconds (ms).
4
+ */
5
+ export function startClock() {
6
+ const start = performance.now()
7
+ return () => performance.now() - start
8
+ }
@@ -0,0 +1,87 @@
1
+ import type { Abi, ExtractAbiEvent, ExtractAbiEventNames } from 'abitype'
2
+ import type { UnknownObject } from '../types'
3
+
4
+ export type EnsureUniqueTuple<
5
+ tuple extends readonly unknown[],
6
+ seen = never,
7
+ > = tuple extends readonly [
8
+ infer head,
9
+ ...infer tail extends readonly unknown[],
10
+ ]
11
+ ? head extends seen
12
+ ? never
13
+ : readonly [head, ...EnsureUniqueTuple<tail, seen | head>]
14
+ : tuple
15
+
16
+ export type MergedContractEvents<
17
+ contracts,
18
+ contractName extends keyof contracts & string = keyof contracts & string,
19
+ > = {
20
+ [name in contractName]: contracts[name] extends {
21
+ events: readonly (infer eventName extends string)[]
22
+ }
23
+ ? `${name}:${eventName}`
24
+ : never
25
+ }[contractName]
26
+
27
+ export interface ContractConfig<
28
+ abi extends Abi,
29
+ events extends
30
+ readonly ExtractAbiEventNames<abi>[] = readonly ExtractAbiEventNames<abi>[],
31
+ > {
32
+ /** Contract application byte interface. */
33
+ abi: abi
34
+ /** Contract address. */
35
+ address: `0x${string}`
36
+ /** Block number at which to start indexing events (inclusive). If `undefined`, events will be processed from block 0. Default: `undefined` */
37
+ startBlock?: bigint
38
+ /** Block number at which to stop indexing events (inclusive). If `undefined`, events will be processed in real-time. Default: `undefined`. */
39
+ endBlock?: bigint
40
+ /** Events to index. No duplicates allowed.*/
41
+ events: EnsureUniqueTuple<events>
42
+ }
43
+
44
+ export type GetContract<contract = unknown> = contract extends {
45
+ abi: infer abi extends Abi
46
+ }
47
+ ? contract extends {
48
+ events: infer events extends readonly ExtractAbiEventNames<abi>[]
49
+ }
50
+ ? // 1. Contract has a valid abi and events
51
+ ContractConfig<abi, events>
52
+ : // 2. Contract has a valid abi
53
+ ContractConfig<abi>
54
+ : // 3. Contract has an invalid abi
55
+ ContractConfig<Abi>
56
+
57
+ export type ContractsConfig<contracts> = UnknownObject extends contracts
58
+ ? // contracts empty, return empty
59
+ UnknownObject
60
+ : {
61
+ [name in keyof contracts]: GetContract<contracts[name]>
62
+ }
63
+
64
+ export type EventKey = `${string}:${string}`
65
+
66
+ export type ContractNameFromEventKey<C extends EventKey> =
67
+ C extends `${infer ContractName}:${string}` ? ContractName : never
68
+
69
+ export type EventNameFromEventKey<K extends string> =
70
+ K extends `${string}:${infer EventName}` ? EventName : never
71
+
72
+ export type ContractAbiByEventKey<
73
+ C extends ContractsConfig<NonNullable<unknown>>,
74
+ Event extends EventKey,
75
+ > = C[Extract<ContractNameFromEventKey<Event>, keyof C>] extends {
76
+ abi: infer ContractAbi extends Abi
77
+ }
78
+ ? ContractAbi
79
+ : Abi
80
+
81
+ export type ContractAbiEventByEventKey<
82
+ C extends ContractsConfig<NonNullable<unknown>>,
83
+ Event extends EventKey,
84
+ > = ExtractAbiEvent<
85
+ ContractAbiByEventKey<C, Event>,
86
+ EventNameFromEventKey<Event>
87
+ >
@@ -0,0 +1,50 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/latest/schema.json",
3
+ "vcs": {
4
+ "enabled": false,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": false
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false
10
+ },
11
+ "formatter": {
12
+ "enabled": true,
13
+ "formatWithErrors": true,
14
+ "indentStyle": "space",
15
+ "indentWidth": 2,
16
+ "lineEnding": "lf",
17
+ "lineWidth": 80,
18
+ "attributePosition": "auto",
19
+ "includes": ["**"]
20
+ },
21
+ "linter": {
22
+ "enabled": true,
23
+ "rules": {
24
+ "recommended": true
25
+ }
26
+ },
27
+ "javascript": {
28
+ "formatter": {
29
+ "jsxQuoteStyle": "double",
30
+ "quoteProperties": "asNeeded",
31
+ "trailingCommas": "es5",
32
+ "semicolons": "asNeeded",
33
+ "arrowParentheses": "always",
34
+ "bracketSpacing": true,
35
+ "bracketSameLine": false,
36
+ "quoteStyle": "single",
37
+ "attributePosition": "auto"
38
+ },
39
+ "globals": ["document", "navigator", "window"]
40
+ },
41
+ "assist": {
42
+ "enabled": true,
43
+ "actions": {
44
+ "source": {
45
+ "organizeImports": "on",
46
+ "useSortedAttributes": "on"
47
+ }
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "foxer-repo",
3
+ "version": "0.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "private": true,
7
+ "workspaces": [
8
+ "apps/*",
9
+ "packages/*"
10
+ ],
11
+ "scripts": {
12
+ "test": "echo \"Error: no test specified\" && exit 1",
13
+ "lint": "pnpm -r --if-present run lint",
14
+ "build": "pnpm -r --if-present run build",
15
+ "lint:fix": "biome check --write ."
16
+ },
17
+ "keywords": [],
18
+ "license": "MIT",
19
+ "devDependencies": {
20
+ "@biomejs/biome": "^2.4.5"
21
+ }
22
+ }
@@ -0,0 +1,3 @@
1
+ packages:
2
+ - 'apps/*'
3
+ - 'packages/*'
@@ -0,0 +1,37 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Projects */
4
+ "incremental": true,
5
+ "composite": true,
6
+ // Emit
7
+
8
+ "declaration": true,
9
+ "declarationMap": true,
10
+ "sourceMap": true,
11
+ "removeComments": true,
12
+
13
+ // Language and Environment
14
+ "lib": ["ESNext", "DOM"],
15
+ "target": "ESNext",
16
+ "moduleDetection": "force",
17
+
18
+ // Modules
19
+ "module": "NodeNext",
20
+ "moduleResolution": "NodeNext",
21
+ "resolveJsonModule": true,
22
+ "rewriteRelativeImportExtensions": true,
23
+
24
+ // Interop Constraints
25
+ "isolatedModules": true,
26
+ "verbatimModuleSyntax": true,
27
+ "erasableSyntaxOnly": true,
28
+ "esModuleInterop": true,
29
+
30
+ // Type Checking
31
+ "strict": true,
32
+ "noImplicitOverride": true,
33
+
34
+ // Completeness
35
+ "skipLibCheck": true
36
+ }
37
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist"
5
+ },
6
+ "include": ["./**/*.ts"],
7
+ "exclude": ["node_modules", "dist"]
8
+ }