@waiaas/daemon 2.0.0-rc.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 (480) hide show
  1. package/dist/api/error-hints.d.ts +15 -0
  2. package/dist/api/error-hints.d.ts.map +1 -0
  3. package/dist/api/error-hints.js +71 -0
  4. package/dist/api/error-hints.js.map +1 -0
  5. package/dist/api/index.d.ts +11 -0
  6. package/dist/api/index.d.ts.map +1 -0
  7. package/dist/api/index.js +14 -0
  8. package/dist/api/index.js.map +1 -0
  9. package/dist/api/middleware/address-validation.d.ts +38 -0
  10. package/dist/api/middleware/address-validation.d.ts.map +1 -0
  11. package/dist/api/middleware/address-validation.js +134 -0
  12. package/dist/api/middleware/address-validation.js.map +1 -0
  13. package/dist/api/middleware/csp.d.ts +17 -0
  14. package/dist/api/middleware/csp.d.ts.map +1 -0
  15. package/dist/api/middleware/csp.js +31 -0
  16. package/dist/api/middleware/csp.js.map +1 -0
  17. package/dist/api/middleware/error-handler.d.ts +16 -0
  18. package/dist/api/middleware/error-handler.d.ts.map +1 -0
  19. package/dist/api/middleware/error-handler.js +46 -0
  20. package/dist/api/middleware/error-handler.js.map +1 -0
  21. package/dist/api/middleware/host-guard.d.ts +11 -0
  22. package/dist/api/middleware/host-guard.d.ts.map +1 -0
  23. package/dist/api/middleware/host-guard.js +25 -0
  24. package/dist/api/middleware/host-guard.js.map +1 -0
  25. package/dist/api/middleware/index.d.ts +13 -0
  26. package/dist/api/middleware/index.d.ts.map +1 -0
  27. package/dist/api/middleware/index.js +13 -0
  28. package/dist/api/middleware/index.js.map +1 -0
  29. package/dist/api/middleware/kill-switch-guard.d.ts +19 -0
  30. package/dist/api/middleware/kill-switch-guard.d.ts.map +1 -0
  31. package/dist/api/middleware/kill-switch-guard.js +49 -0
  32. package/dist/api/middleware/kill-switch-guard.js.map +1 -0
  33. package/dist/api/middleware/master-auth.d.ts +15 -0
  34. package/dist/api/middleware/master-auth.d.ts.map +1 -0
  35. package/dist/api/middleware/master-auth.js +35 -0
  36. package/dist/api/middleware/master-auth.js.map +1 -0
  37. package/dist/api/middleware/owner-auth.d.ts +30 -0
  38. package/dist/api/middleware/owner-auth.d.ts.map +1 -0
  39. package/dist/api/middleware/owner-auth.js +133 -0
  40. package/dist/api/middleware/owner-auth.js.map +1 -0
  41. package/dist/api/middleware/request-id.d.ts +10 -0
  42. package/dist/api/middleware/request-id.d.ts.map +1 -0
  43. package/dist/api/middleware/request-id.js +18 -0
  44. package/dist/api/middleware/request-id.js.map +1 -0
  45. package/dist/api/middleware/request-logger.d.ts +9 -0
  46. package/dist/api/middleware/request-logger.d.ts.map +1 -0
  47. package/dist/api/middleware/request-logger.js +18 -0
  48. package/dist/api/middleware/request-logger.js.map +1 -0
  49. package/dist/api/middleware/session-auth.d.ts +21 -0
  50. package/dist/api/middleware/session-auth.d.ts.map +1 -0
  51. package/dist/api/middleware/session-auth.js +51 -0
  52. package/dist/api/middleware/session-auth.js.map +1 -0
  53. package/dist/api/middleware/siwe-verify.d.ts +31 -0
  54. package/dist/api/middleware/siwe-verify.d.ts.map +1 -0
  55. package/dist/api/middleware/siwe-verify.js +55 -0
  56. package/dist/api/middleware/siwe-verify.js.map +1 -0
  57. package/dist/api/routes/actions.d.ts +56 -0
  58. package/dist/api/routes/actions.d.ts.map +1 -0
  59. package/dist/api/routes/actions.js +291 -0
  60. package/dist/api/routes/actions.js.map +1 -0
  61. package/dist/api/routes/admin.d.ts +99 -0
  62. package/dist/api/routes/admin.d.ts.map +1 -0
  63. package/dist/api/routes/admin.js +1304 -0
  64. package/dist/api/routes/admin.js.map +1 -0
  65. package/dist/api/routes/display-currency-helper.d.ts +26 -0
  66. package/dist/api/routes/display-currency-helper.d.ts.map +1 -0
  67. package/dist/api/routes/display-currency-helper.js +47 -0
  68. package/dist/api/routes/display-currency-helper.js.map +1 -0
  69. package/dist/api/routes/health.d.ts +14 -0
  70. package/dist/api/routes/health.d.ts.map +1 -0
  71. package/dist/api/routes/health.js +47 -0
  72. package/dist/api/routes/health.js.map +1 -0
  73. package/dist/api/routes/index.d.ts +15 -0
  74. package/dist/api/routes/index.d.ts.map +1 -0
  75. package/dist/api/routes/index.js +15 -0
  76. package/dist/api/routes/index.js.map +1 -0
  77. package/dist/api/routes/mcp.d.ts +30 -0
  78. package/dist/api/routes/mcp.d.ts.map +1 -0
  79. package/dist/api/routes/mcp.js +156 -0
  80. package/dist/api/routes/mcp.js.map +1 -0
  81. package/dist/api/routes/nonce.d.ts +20 -0
  82. package/dist/api/routes/nonce.d.ts.map +1 -0
  83. package/dist/api/routes/nonce.js +48 -0
  84. package/dist/api/routes/nonce.js.map +1 -0
  85. package/dist/api/routes/openapi-schemas.d.ts +2281 -0
  86. package/dist/api/routes/openapi-schemas.d.ts.map +1 -0
  87. package/dist/api/routes/openapi-schemas.js +770 -0
  88. package/dist/api/routes/openapi-schemas.js.map +1 -0
  89. package/dist/api/routes/policies.d.ts +29 -0
  90. package/dist/api/routes/policies.d.ts.map +1 -0
  91. package/dist/api/routes/policies.js +332 -0
  92. package/dist/api/routes/policies.js.map +1 -0
  93. package/dist/api/routes/sessions.d.ts +35 -0
  94. package/dist/api/routes/sessions.d.ts.map +1 -0
  95. package/dist/api/routes/sessions.js +347 -0
  96. package/dist/api/routes/sessions.js.map +1 -0
  97. package/dist/api/routes/skills.d.ts +9 -0
  98. package/dist/api/routes/skills.d.ts.map +1 -0
  99. package/dist/api/routes/skills.js +59 -0
  100. package/dist/api/routes/skills.js.map +1 -0
  101. package/dist/api/routes/tokens.d.ts +25 -0
  102. package/dist/api/routes/tokens.d.ts.map +1 -0
  103. package/dist/api/routes/tokens.js +161 -0
  104. package/dist/api/routes/tokens.js.map +1 -0
  105. package/dist/api/routes/transactions.d.ts +68 -0
  106. package/dist/api/routes/transactions.d.ts.map +1 -0
  107. package/dist/api/routes/transactions.js +576 -0
  108. package/dist/api/routes/transactions.js.map +1 -0
  109. package/dist/api/routes/utils.d.ts +9 -0
  110. package/dist/api/routes/utils.d.ts.map +1 -0
  111. package/dist/api/routes/utils.js +52 -0
  112. package/dist/api/routes/utils.js.map +1 -0
  113. package/dist/api/routes/wallet.d.ts +36 -0
  114. package/dist/api/routes/wallet.d.ts.map +1 -0
  115. package/dist/api/routes/wallet.js +358 -0
  116. package/dist/api/routes/wallet.js.map +1 -0
  117. package/dist/api/routes/wallets.d.ts +43 -0
  118. package/dist/api/routes/wallets.d.ts.map +1 -0
  119. package/dist/api/routes/wallets.js +630 -0
  120. package/dist/api/routes/wallets.js.map +1 -0
  121. package/dist/api/routes/wc.d.ts +46 -0
  122. package/dist/api/routes/wc.d.ts.map +1 -0
  123. package/dist/api/routes/wc.js +354 -0
  124. package/dist/api/routes/wc.js.map +1 -0
  125. package/dist/api/routes/x402.d.ts +61 -0
  126. package/dist/api/routes/x402.d.ts.map +1 -0
  127. package/dist/api/routes/x402.js +493 -0
  128. package/dist/api/routes/x402.js.map +1 -0
  129. package/dist/api/server.d.ts +81 -0
  130. package/dist/api/server.d.ts.map +1 -0
  131. package/dist/api/server.js +406 -0
  132. package/dist/api/server.js.map +1 -0
  133. package/dist/index.d.ts +35 -0
  134. package/dist/index.d.ts.map +1 -0
  135. package/dist/index.js +43 -0
  136. package/dist/index.js.map +1 -0
  137. package/dist/infrastructure/action/action-provider-registry.d.ts +77 -0
  138. package/dist/infrastructure/action/action-provider-registry.d.ts.map +1 -0
  139. package/dist/infrastructure/action/action-provider-registry.js +239 -0
  140. package/dist/infrastructure/action/action-provider-registry.js.map +1 -0
  141. package/dist/infrastructure/action/api-key-store.d.ts +60 -0
  142. package/dist/infrastructure/action/api-key-store.d.ts.map +1 -0
  143. package/dist/infrastructure/action/api-key-store.js +130 -0
  144. package/dist/infrastructure/action/api-key-store.js.map +1 -0
  145. package/dist/infrastructure/action/index.d.ts +10 -0
  146. package/dist/infrastructure/action/index.d.ts.map +1 -0
  147. package/dist/infrastructure/action/index.js +9 -0
  148. package/dist/infrastructure/action/index.js.map +1 -0
  149. package/dist/infrastructure/adapter-pool.d.ts +50 -0
  150. package/dist/infrastructure/adapter-pool.d.ts.map +1 -0
  151. package/dist/infrastructure/adapter-pool.js +110 -0
  152. package/dist/infrastructure/adapter-pool.js.map +1 -0
  153. package/dist/infrastructure/backup/backup-service.d.ts +53 -0
  154. package/dist/infrastructure/backup/backup-service.d.ts.map +1 -0
  155. package/dist/infrastructure/backup/backup-service.js +158 -0
  156. package/dist/infrastructure/backup/backup-service.js.map +1 -0
  157. package/dist/infrastructure/backup/index.d.ts +2 -0
  158. package/dist/infrastructure/backup/index.d.ts.map +1 -0
  159. package/dist/infrastructure/backup/index.js +2 -0
  160. package/dist/infrastructure/backup/index.js.map +1 -0
  161. package/dist/infrastructure/config/index.d.ts +8 -0
  162. package/dist/infrastructure/config/index.d.ts.map +1 -0
  163. package/dist/infrastructure/config/index.js +7 -0
  164. package/dist/infrastructure/config/index.js.map +1 -0
  165. package/dist/infrastructure/config/loader.d.ts +555 -0
  166. package/dist/infrastructure/config/loader.d.ts.map +1 -0
  167. package/dist/infrastructure/config/loader.js +311 -0
  168. package/dist/infrastructure/config/loader.js.map +1 -0
  169. package/dist/infrastructure/database/checks.d.ts +19 -0
  170. package/dist/infrastructure/database/checks.d.ts.map +1 -0
  171. package/dist/infrastructure/database/checks.js +27 -0
  172. package/dist/infrastructure/database/checks.js.map +1 -0
  173. package/dist/infrastructure/database/compatibility.d.ts +36 -0
  174. package/dist/infrastructure/database/compatibility.d.ts.map +1 -0
  175. package/dist/infrastructure/database/compatibility.js +75 -0
  176. package/dist/infrastructure/database/compatibility.js.map +1 -0
  177. package/dist/infrastructure/database/connection.d.ts +36 -0
  178. package/dist/infrastructure/database/connection.d.ts.map +1 -0
  179. package/dist/infrastructure/database/connection.js +47 -0
  180. package/dist/infrastructure/database/connection.js.map +1 -0
  181. package/dist/infrastructure/database/id.d.ts +17 -0
  182. package/dist/infrastructure/database/id.d.ts.map +1 -0
  183. package/dist/infrastructure/database/id.js +20 -0
  184. package/dist/infrastructure/database/id.js.map +1 -0
  185. package/dist/infrastructure/database/index.d.ts +15 -0
  186. package/dist/infrastructure/database/index.d.ts.map +1 -0
  187. package/dist/infrastructure/database/index.js +12 -0
  188. package/dist/infrastructure/database/index.js.map +1 -0
  189. package/dist/infrastructure/database/migrate.d.ts +76 -0
  190. package/dist/infrastructure/database/migrate.d.ts.map +1 -0
  191. package/dist/infrastructure/database/migrate.js +1214 -0
  192. package/dist/infrastructure/database/migrate.js.map +1 -0
  193. package/dist/infrastructure/database/schema.d.ts +2352 -0
  194. package/dist/infrastructure/database/schema.d.ts.map +1 -0
  195. package/dist/infrastructure/database/schema.js +288 -0
  196. package/dist/infrastructure/database/schema.js.map +1 -0
  197. package/dist/infrastructure/jwt/index.d.ts +2 -0
  198. package/dist/infrastructure/jwt/index.d.ts.map +1 -0
  199. package/dist/infrastructure/jwt/index.js +2 -0
  200. package/dist/infrastructure/jwt/index.js.map +1 -0
  201. package/dist/infrastructure/jwt/jwt-secret-manager.d.ts +58 -0
  202. package/dist/infrastructure/jwt/jwt-secret-manager.d.ts.map +1 -0
  203. package/dist/infrastructure/jwt/jwt-secret-manager.js +222 -0
  204. package/dist/infrastructure/jwt/jwt-secret-manager.js.map +1 -0
  205. package/dist/infrastructure/keystore/crypto.d.ts +62 -0
  206. package/dist/infrastructure/keystore/crypto.d.ts.map +1 -0
  207. package/dist/infrastructure/keystore/crypto.js +89 -0
  208. package/dist/infrastructure/keystore/crypto.js.map +1 -0
  209. package/dist/infrastructure/keystore/index.d.ts +4 -0
  210. package/dist/infrastructure/keystore/index.d.ts.map +1 -0
  211. package/dist/infrastructure/keystore/index.js +5 -0
  212. package/dist/infrastructure/keystore/index.js.map +1 -0
  213. package/dist/infrastructure/keystore/keystore.d.ts +115 -0
  214. package/dist/infrastructure/keystore/keystore.d.ts.map +1 -0
  215. package/dist/infrastructure/keystore/keystore.js +327 -0
  216. package/dist/infrastructure/keystore/keystore.js.map +1 -0
  217. package/dist/infrastructure/keystore/memory.d.ts +45 -0
  218. package/dist/infrastructure/keystore/memory.d.ts.map +1 -0
  219. package/dist/infrastructure/keystore/memory.js +105 -0
  220. package/dist/infrastructure/keystore/memory.js.map +1 -0
  221. package/dist/infrastructure/oracle/coingecko-forex.d.ts +35 -0
  222. package/dist/infrastructure/oracle/coingecko-forex.d.ts.map +1 -0
  223. package/dist/infrastructure/oracle/coingecko-forex.js +69 -0
  224. package/dist/infrastructure/oracle/coingecko-forex.js.map +1 -0
  225. package/dist/infrastructure/oracle/coingecko-oracle.d.ts +73 -0
  226. package/dist/infrastructure/oracle/coingecko-oracle.d.ts.map +1 -0
  227. package/dist/infrastructure/oracle/coingecko-oracle.js +199 -0
  228. package/dist/infrastructure/oracle/coingecko-oracle.js.map +1 -0
  229. package/dist/infrastructure/oracle/coingecko-platform-ids.d.ts +32 -0
  230. package/dist/infrastructure/oracle/coingecko-platform-ids.d.ts.map +1 -0
  231. package/dist/infrastructure/oracle/coingecko-platform-ids.js +30 -0
  232. package/dist/infrastructure/oracle/coingecko-platform-ids.js.map +1 -0
  233. package/dist/infrastructure/oracle/forex-currencies.d.ts +36 -0
  234. package/dist/infrastructure/oracle/forex-currencies.d.ts.map +1 -0
  235. package/dist/infrastructure/oracle/forex-currencies.js +71 -0
  236. package/dist/infrastructure/oracle/forex-currencies.js.map +1 -0
  237. package/dist/infrastructure/oracle/forex-rate-service.d.ts +51 -0
  238. package/dist/infrastructure/oracle/forex-rate-service.d.ts.map +1 -0
  239. package/dist/infrastructure/oracle/forex-rate-service.js +149 -0
  240. package/dist/infrastructure/oracle/forex-rate-service.js.map +1 -0
  241. package/dist/infrastructure/oracle/index.d.ts +18 -0
  242. package/dist/infrastructure/oracle/index.d.ts.map +1 -0
  243. package/dist/infrastructure/oracle/index.js +19 -0
  244. package/dist/infrastructure/oracle/index.js.map +1 -0
  245. package/dist/infrastructure/oracle/oracle-chain.d.ts +101 -0
  246. package/dist/infrastructure/oracle/oracle-chain.d.ts.map +1 -0
  247. package/dist/infrastructure/oracle/oracle-chain.js +163 -0
  248. package/dist/infrastructure/oracle/oracle-chain.js.map +1 -0
  249. package/dist/infrastructure/oracle/oracle-errors.d.ts +42 -0
  250. package/dist/infrastructure/oracle/oracle-errors.d.ts.map +1 -0
  251. package/dist/infrastructure/oracle/oracle-errors.js +53 -0
  252. package/dist/infrastructure/oracle/oracle-errors.js.map +1 -0
  253. package/dist/infrastructure/oracle/price-age.d.ts +38 -0
  254. package/dist/infrastructure/oracle/price-age.d.ts.map +1 -0
  255. package/dist/infrastructure/oracle/price-age.js +44 -0
  256. package/dist/infrastructure/oracle/price-age.js.map +1 -0
  257. package/dist/infrastructure/oracle/price-cache.d.ts +99 -0
  258. package/dist/infrastructure/oracle/price-cache.d.ts.map +1 -0
  259. package/dist/infrastructure/oracle/price-cache.js +173 -0
  260. package/dist/infrastructure/oracle/price-cache.js.map +1 -0
  261. package/dist/infrastructure/oracle/pyth-feed-ids.d.ts +31 -0
  262. package/dist/infrastructure/oracle/pyth-feed-ids.d.ts.map +1 -0
  263. package/dist/infrastructure/oracle/pyth-feed-ids.js +44 -0
  264. package/dist/infrastructure/oracle/pyth-feed-ids.js.map +1 -0
  265. package/dist/infrastructure/oracle/pyth-oracle.d.ts +69 -0
  266. package/dist/infrastructure/oracle/pyth-oracle.d.ts.map +1 -0
  267. package/dist/infrastructure/oracle/pyth-oracle.js +149 -0
  268. package/dist/infrastructure/oracle/pyth-oracle.js.map +1 -0
  269. package/dist/infrastructure/settings/hot-reload.d.ts +71 -0
  270. package/dist/infrastructure/settings/hot-reload.d.ts.map +1 -0
  271. package/dist/infrastructure/settings/hot-reload.js +315 -0
  272. package/dist/infrastructure/settings/hot-reload.js.map +1 -0
  273. package/dist/infrastructure/settings/index.d.ts +13 -0
  274. package/dist/infrastructure/settings/index.d.ts.map +1 -0
  275. package/dist/infrastructure/settings/index.js +10 -0
  276. package/dist/infrastructure/settings/index.js.map +1 -0
  277. package/dist/infrastructure/settings/setting-keys.d.ts +28 -0
  278. package/dist/infrastructure/settings/setting-keys.d.ts.map +1 -0
  279. package/dist/infrastructure/settings/setting-keys.js +105 -0
  280. package/dist/infrastructure/settings/setting-keys.js.map +1 -0
  281. package/dist/infrastructure/settings/settings-crypto.d.ts +39 -0
  282. package/dist/infrastructure/settings/settings-crypto.d.ts.map +1 -0
  283. package/dist/infrastructure/settings/settings-crypto.js +73 -0
  284. package/dist/infrastructure/settings/settings-crypto.js.map +1 -0
  285. package/dist/infrastructure/settings/settings-service.d.ts +82 -0
  286. package/dist/infrastructure/settings/settings-service.d.ts.map +1 -0
  287. package/dist/infrastructure/settings/settings-service.js +267 -0
  288. package/dist/infrastructure/settings/settings-service.js.map +1 -0
  289. package/dist/infrastructure/telegram/index.d.ts +6 -0
  290. package/dist/infrastructure/telegram/index.d.ts.map +1 -0
  291. package/dist/infrastructure/telegram/index.js +5 -0
  292. package/dist/infrastructure/telegram/index.js.map +1 -0
  293. package/dist/infrastructure/telegram/telegram-api.d.ts +35 -0
  294. package/dist/infrastructure/telegram/telegram-api.d.ts.map +1 -0
  295. package/dist/infrastructure/telegram/telegram-api.js +82 -0
  296. package/dist/infrastructure/telegram/telegram-api.js.map +1 -0
  297. package/dist/infrastructure/telegram/telegram-auth.d.ts +57 -0
  298. package/dist/infrastructure/telegram/telegram-auth.d.ts.map +1 -0
  299. package/dist/infrastructure/telegram/telegram-auth.js +88 -0
  300. package/dist/infrastructure/telegram/telegram-auth.js.map +1 -0
  301. package/dist/infrastructure/telegram/telegram-bot-service.d.ts +95 -0
  302. package/dist/infrastructure/telegram/telegram-bot-service.d.ts.map +1 -0
  303. package/dist/infrastructure/telegram/telegram-bot-service.js +564 -0
  304. package/dist/infrastructure/telegram/telegram-bot-service.js.map +1 -0
  305. package/dist/infrastructure/telegram/telegram-keyboard.d.ts +27 -0
  306. package/dist/infrastructure/telegram/telegram-keyboard.d.ts.map +1 -0
  307. package/dist/infrastructure/telegram/telegram-keyboard.js +52 -0
  308. package/dist/infrastructure/telegram/telegram-keyboard.js.map +1 -0
  309. package/dist/infrastructure/telegram/telegram-types.d.ts +43 -0
  310. package/dist/infrastructure/telegram/telegram-types.d.ts.map +1 -0
  311. package/dist/infrastructure/telegram/telegram-types.js +8 -0
  312. package/dist/infrastructure/telegram/telegram-types.js.map +1 -0
  313. package/dist/infrastructure/token-registry/builtin-tokens.d.ts +39 -0
  314. package/dist/infrastructure/token-registry/builtin-tokens.d.ts.map +1 -0
  315. package/dist/infrastructure/token-registry/builtin-tokens.js +135 -0
  316. package/dist/infrastructure/token-registry/builtin-tokens.js.map +1 -0
  317. package/dist/infrastructure/token-registry/index.d.ts +8 -0
  318. package/dist/infrastructure/token-registry/index.d.ts.map +1 -0
  319. package/dist/infrastructure/token-registry/index.js +8 -0
  320. package/dist/infrastructure/token-registry/index.js.map +1 -0
  321. package/dist/infrastructure/token-registry/token-registry-service.d.ts +49 -0
  322. package/dist/infrastructure/token-registry/token-registry-service.d.ts.map +1 -0
  323. package/dist/infrastructure/token-registry/token-registry-service.js +93 -0
  324. package/dist/infrastructure/token-registry/token-registry-service.js.map +1 -0
  325. package/dist/infrastructure/version/index.d.ts +5 -0
  326. package/dist/infrastructure/version/index.d.ts.map +1 -0
  327. package/dist/infrastructure/version/index.js +5 -0
  328. package/dist/infrastructure/version/index.js.map +1 -0
  329. package/dist/infrastructure/version/version-check-service.d.ts +35 -0
  330. package/dist/infrastructure/version/version-check-service.d.ts.map +1 -0
  331. package/dist/infrastructure/version/version-check-service.js +92 -0
  332. package/dist/infrastructure/version/version-check-service.js.map +1 -0
  333. package/dist/lifecycle/daemon.d.ts +103 -0
  334. package/dist/lifecycle/daemon.d.ts.map +1 -0
  335. package/dist/lifecycle/daemon.js +934 -0
  336. package/dist/lifecycle/daemon.js.map +1 -0
  337. package/dist/lifecycle/index.d.ts +9 -0
  338. package/dist/lifecycle/index.d.ts.map +1 -0
  339. package/dist/lifecycle/index.js +9 -0
  340. package/dist/lifecycle/index.js.map +1 -0
  341. package/dist/lifecycle/signal-handler.d.ts +18 -0
  342. package/dist/lifecycle/signal-handler.d.ts.map +1 -0
  343. package/dist/lifecycle/signal-handler.js +37 -0
  344. package/dist/lifecycle/signal-handler.js.map +1 -0
  345. package/dist/lifecycle/workers.d.ts +46 -0
  346. package/dist/lifecycle/workers.d.ts.map +1 -0
  347. package/dist/lifecycle/workers.js +101 -0
  348. package/dist/lifecycle/workers.js.map +1 -0
  349. package/dist/notifications/channels/discord.d.ts +10 -0
  350. package/dist/notifications/channels/discord.d.ts.map +1 -0
  351. package/dist/notifications/channels/discord.js +54 -0
  352. package/dist/notifications/channels/discord.js.map +1 -0
  353. package/dist/notifications/channels/ntfy.d.ts +13 -0
  354. package/dist/notifications/channels/ntfy.d.ts.map +1 -0
  355. package/dist/notifications/channels/ntfy.js +58 -0
  356. package/dist/notifications/channels/ntfy.js.map +1 -0
  357. package/dist/notifications/channels/slack.d.ts +10 -0
  358. package/dist/notifications/channels/slack.d.ts.map +1 -0
  359. package/dist/notifications/channels/slack.js +55 -0
  360. package/dist/notifications/channels/slack.js.map +1 -0
  361. package/dist/notifications/channels/telegram.d.ts +10 -0
  362. package/dist/notifications/channels/telegram.d.ts.map +1 -0
  363. package/dist/notifications/channels/telegram.js +40 -0
  364. package/dist/notifications/channels/telegram.js.map +1 -0
  365. package/dist/notifications/index.d.ts +9 -0
  366. package/dist/notifications/index.d.ts.map +1 -0
  367. package/dist/notifications/index.js +7 -0
  368. package/dist/notifications/index.js.map +1 -0
  369. package/dist/notifications/notification-service.d.ts +75 -0
  370. package/dist/notifications/notification-service.d.ts.map +1 -0
  371. package/dist/notifications/notification-service.js +213 -0
  372. package/dist/notifications/notification-service.js.map +1 -0
  373. package/dist/notifications/templates/message-templates.d.ts +12 -0
  374. package/dist/notifications/templates/message-templates.d.ts.map +1 -0
  375. package/dist/notifications/templates/message-templates.js +22 -0
  376. package/dist/notifications/templates/message-templates.js.map +1 -0
  377. package/dist/pipeline/database-policy-engine.d.ts +286 -0
  378. package/dist/pipeline/database-policy-engine.d.ts.map +1 -0
  379. package/dist/pipeline/database-policy-engine.js +992 -0
  380. package/dist/pipeline/database-policy-engine.js.map +1 -0
  381. package/dist/pipeline/default-policy-engine.d.ts +26 -0
  382. package/dist/pipeline/default-policy-engine.d.ts.map +1 -0
  383. package/dist/pipeline/default-policy-engine.js +25 -0
  384. package/dist/pipeline/default-policy-engine.js.map +1 -0
  385. package/dist/pipeline/index.d.ts +9 -0
  386. package/dist/pipeline/index.d.ts.map +1 -0
  387. package/dist/pipeline/index.js +9 -0
  388. package/dist/pipeline/index.js.map +1 -0
  389. package/dist/pipeline/network-resolver.d.ts +22 -0
  390. package/dist/pipeline/network-resolver.d.ts.map +1 -0
  391. package/dist/pipeline/network-resolver.js +32 -0
  392. package/dist/pipeline/network-resolver.js.map +1 -0
  393. package/dist/pipeline/pipeline.d.ts +72 -0
  394. package/dist/pipeline/pipeline.d.ts.map +1 -0
  395. package/dist/pipeline/pipeline.js +87 -0
  396. package/dist/pipeline/pipeline.js.map +1 -0
  397. package/dist/pipeline/resolve-effective-amount-usd.d.ts +41 -0
  398. package/dist/pipeline/resolve-effective-amount-usd.d.ts.map +1 -0
  399. package/dist/pipeline/resolve-effective-amount-usd.js +208 -0
  400. package/dist/pipeline/resolve-effective-amount-usd.js.map +1 -0
  401. package/dist/pipeline/sign-only.d.ts +99 -0
  402. package/dist/pipeline/sign-only.d.ts.map +1 -0
  403. package/dist/pipeline/sign-only.js +267 -0
  404. package/dist/pipeline/sign-only.js.map +1 -0
  405. package/dist/pipeline/sleep.d.ts +6 -0
  406. package/dist/pipeline/sleep.d.ts.map +1 -0
  407. package/dist/pipeline/sleep.js +8 -0
  408. package/dist/pipeline/sleep.js.map +1 -0
  409. package/dist/pipeline/stages.d.ts +82 -0
  410. package/dist/pipeline/stages.d.ts.map +1 -0
  411. package/dist/pipeline/stages.js +784 -0
  412. package/dist/pipeline/stages.js.map +1 -0
  413. package/dist/services/autostop-rules.d.ts +79 -0
  414. package/dist/services/autostop-rules.d.ts.map +1 -0
  415. package/dist/services/autostop-rules.js +174 -0
  416. package/dist/services/autostop-rules.js.map +1 -0
  417. package/dist/services/autostop-service.d.ts +82 -0
  418. package/dist/services/autostop-service.d.ts.map +1 -0
  419. package/dist/services/autostop-service.js +223 -0
  420. package/dist/services/autostop-service.js.map +1 -0
  421. package/dist/services/kill-switch-service.d.ts +118 -0
  422. package/dist/services/kill-switch-service.d.ts.map +1 -0
  423. package/dist/services/kill-switch-service.js +291 -0
  424. package/dist/services/kill-switch-service.js.map +1 -0
  425. package/dist/services/monitoring/balance-monitor-service.d.ts +65 -0
  426. package/dist/services/monitoring/balance-monitor-service.d.ts.map +1 -0
  427. package/dist/services/monitoring/balance-monitor-service.js +207 -0
  428. package/dist/services/monitoring/balance-monitor-service.js.map +1 -0
  429. package/dist/services/wc-session-service.d.ts +123 -0
  430. package/dist/services/wc-session-service.d.ts.map +1 -0
  431. package/dist/services/wc-session-service.js +363 -0
  432. package/dist/services/wc-session-service.js.map +1 -0
  433. package/dist/services/wc-signing-bridge.d.ts +60 -0
  434. package/dist/services/wc-signing-bridge.d.ts.map +1 -0
  435. package/dist/services/wc-signing-bridge.js +334 -0
  436. package/dist/services/wc-signing-bridge.js.map +1 -0
  437. package/dist/services/wc-storage.d.ts +32 -0
  438. package/dist/services/wc-storage.d.ts.map +1 -0
  439. package/dist/services/wc-storage.js +64 -0
  440. package/dist/services/wc-storage.js.map +1 -0
  441. package/dist/services/x402/payment-signer.d.ts +88 -0
  442. package/dist/services/x402/payment-signer.d.ts.map +1 -0
  443. package/dist/services/x402/payment-signer.js +311 -0
  444. package/dist/services/x402/payment-signer.js.map +1 -0
  445. package/dist/services/x402/ssrf-guard.d.ts +27 -0
  446. package/dist/services/x402/ssrf-guard.d.ts.map +1 -0
  447. package/dist/services/x402/ssrf-guard.js +236 -0
  448. package/dist/services/x402/ssrf-guard.js.map +1 -0
  449. package/dist/services/x402/x402-domain-policy.d.ts +50 -0
  450. package/dist/services/x402/x402-domain-policy.d.ts.map +1 -0
  451. package/dist/services/x402/x402-domain-policy.js +78 -0
  452. package/dist/services/x402/x402-domain-policy.js.map +1 -0
  453. package/dist/services/x402/x402-handler.d.ts +71 -0
  454. package/dist/services/x402/x402-handler.d.ts.map +1 -0
  455. package/dist/services/x402/x402-handler.js +195 -0
  456. package/dist/services/x402/x402-handler.js.map +1 -0
  457. package/dist/services/x402/x402-usd-resolver.d.ts +26 -0
  458. package/dist/services/x402/x402-usd-resolver.d.ts.map +1 -0
  459. package/dist/services/x402/x402-usd-resolver.js +79 -0
  460. package/dist/services/x402/x402-usd-resolver.js.map +1 -0
  461. package/dist/workflow/approval-workflow.d.ts +103 -0
  462. package/dist/workflow/approval-workflow.d.ts.map +1 -0
  463. package/dist/workflow/approval-workflow.js +202 -0
  464. package/dist/workflow/approval-workflow.js.map +1 -0
  465. package/dist/workflow/delay-queue.d.ts +78 -0
  466. package/dist/workflow/delay-queue.d.ts.map +1 -0
  467. package/dist/workflow/delay-queue.js +174 -0
  468. package/dist/workflow/delay-queue.js.map +1 -0
  469. package/dist/workflow/index.d.ts +11 -0
  470. package/dist/workflow/index.d.ts.map +1 -0
  471. package/dist/workflow/index.js +9 -0
  472. package/dist/workflow/index.js.map +1 -0
  473. package/dist/workflow/owner-state.d.ts +97 -0
  474. package/dist/workflow/owner-state.d.ts.map +1 -0
  475. package/dist/workflow/owner-state.js +168 -0
  476. package/dist/workflow/owner-state.js.map +1 -0
  477. package/package.json +71 -0
  478. package/public/admin/assets/index-BPoUSH8W.css +1 -0
  479. package/public/admin/assets/index-CDi1qoXB.js +1 -0
  480. package/public/admin/index.html +13 -0
@@ -0,0 +1,784 @@
1
+ /**
2
+ * 6-stage transaction pipeline stages.
3
+ *
4
+ * Stage 1: Validate request + INSERT PENDING transaction (with sessionId audit trail)
5
+ * Stage 2: Auth (sessionId passthrough from route handler)
6
+ * Stage 3: Policy evaluation (evaluateAndReserve TOCTOU-safe + downgradeIfNoOwner)
7
+ * Stage 4: Wait (v1.1 passthrough, INSTANT tier only)
8
+ * Stage 5: On-chain execution (build -> simulate -> sign -> submit)
9
+ * Stage 6: Confirmation wait
10
+ *
11
+ * @see docs/32-pipeline-design.md
12
+ */
13
+ import { eq } from 'drizzle-orm';
14
+ import { WAIaaSError, ChainError, SendTransactionRequestSchema, TransactionRequestSchema, } from '@waiaas/core';
15
+ import { wallets, transactions, auditLog } from '../infrastructure/database/schema.js';
16
+ import { generateId } from '../infrastructure/database/id.js';
17
+ import { DatabasePolicyEngine } from './database-policy-engine.js';
18
+ import { downgradeIfNoOwner } from '../workflow/owner-state.js';
19
+ import { formatDisplayCurrency } from '@waiaas/core';
20
+ import { resolveEffectiveAmountUsd } from './resolve-effective-amount-usd.js';
21
+ import { sleep } from './sleep.js';
22
+ // v1.5: CoinGecko 키 안내 힌트 최초 1회 추적 (데몬 재시작 시 리셋 OK)
23
+ const hintedTokens = new Set();
24
+ // Exported for test cleanup
25
+ export { hintedTokens };
26
+ // ---------------------------------------------------------------------------
27
+ // Helper: safe request field accessors for union type
28
+ // ---------------------------------------------------------------------------
29
+ /** Safely extract `amount` from SendTransactionRequest | TransactionRequest. */
30
+ function getRequestAmount(req) {
31
+ if ('amount' in req && typeof req.amount === 'string')
32
+ return req.amount;
33
+ return '0';
34
+ }
35
+ /** Safely extract `to` from SendTransactionRequest | TransactionRequest. */
36
+ function getRequestTo(req) {
37
+ if ('to' in req && typeof req.to === 'string')
38
+ return req.to;
39
+ return '';
40
+ }
41
+ /** Safely extract `memo` from SendTransactionRequest | TransactionRequest. */
42
+ function getRequestMemo(req) {
43
+ if ('memo' in req && typeof req.memo === 'string')
44
+ return req.memo;
45
+ return undefined;
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Helper: resolve display amount for notification messages
49
+ // ---------------------------------------------------------------------------
50
+ /**
51
+ * Convert amountUsd to display currency string for notification variables.
52
+ * Returns empty string on failure (graceful fallback -- no display_amount in message).
53
+ */
54
+ async function resolveDisplayAmount(amountUsd, settingsService, forexRateService) {
55
+ if (!amountUsd || !settingsService || !forexRateService)
56
+ return '';
57
+ try {
58
+ const currency = settingsService.get('display.currency') ?? 'USD';
59
+ if (currency === 'USD')
60
+ return `($${amountUsd.toFixed(2)})`;
61
+ const rate = await forexRateService.getRate(currency);
62
+ if (!rate)
63
+ return `($${amountUsd.toFixed(2)})`;
64
+ return `(${formatDisplayCurrency(amountUsd, currency, rate.rate)})`;
65
+ }
66
+ catch {
67
+ return '';
68
+ }
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Helper: extract policy type from evaluation reason string
72
+ // ---------------------------------------------------------------------------
73
+ function extractPolicyType(reason) {
74
+ if (!reason)
75
+ return '';
76
+ if (reason.includes('not in allowed list') || reason.includes('Token transfer not allowed'))
77
+ return 'ALLOWED_TOKENS';
78
+ if (reason.includes('not whitelisted') || reason.includes('Contract calls disabled'))
79
+ return 'CONTRACT_WHITELIST';
80
+ if (reason.includes('Method not whitelisted'))
81
+ return 'METHOD_WHITELIST';
82
+ if (reason.includes('not in approved list') || reason.includes('Token approvals disabled'))
83
+ return 'APPROVED_SPENDERS';
84
+ if (reason.includes('not in whitelist') || reason.includes('not in allowed addresses'))
85
+ return 'WHITELIST';
86
+ if (reason.includes('not in allowed networks'))
87
+ return 'ALLOWED_NETWORKS';
88
+ if (reason.includes('exceeds limit') || reason.includes('Unlimited token approval'))
89
+ return 'APPROVE_AMOUNT_LIMIT';
90
+ if (reason.includes('Spending limit'))
91
+ return 'SPENDING_LIMIT';
92
+ return '';
93
+ }
94
+ function buildTransactionParam(req, txType, chain) {
95
+ switch (txType) {
96
+ case 'TOKEN_TRANSFER': {
97
+ const r = req;
98
+ return {
99
+ type: 'TOKEN_TRANSFER',
100
+ amount: r.amount,
101
+ toAddress: r.to,
102
+ chain,
103
+ tokenAddress: r.token.address,
104
+ };
105
+ }
106
+ case 'CONTRACT_CALL': {
107
+ const r = req;
108
+ return {
109
+ type: 'CONTRACT_CALL',
110
+ amount: r.value ?? '0',
111
+ toAddress: r.to,
112
+ chain,
113
+ contractAddress: r.to,
114
+ selector: r.calldata?.slice(0, 10),
115
+ };
116
+ }
117
+ case 'APPROVE': {
118
+ const r = req;
119
+ return {
120
+ type: 'APPROVE',
121
+ amount: r.amount,
122
+ toAddress: r.spender,
123
+ chain,
124
+ spenderAddress: r.spender,
125
+ approveAmount: r.amount,
126
+ };
127
+ }
128
+ case 'TRANSFER':
129
+ default: {
130
+ const r = req;
131
+ return {
132
+ type: 'TRANSFER',
133
+ amount: r.amount,
134
+ toAddress: r.to,
135
+ chain,
136
+ };
137
+ }
138
+ }
139
+ }
140
+ // ---------------------------------------------------------------------------
141
+ // Stage 1: Validate + DB INSERT
142
+ // ---------------------------------------------------------------------------
143
+ export async function stage1Validate(ctx) {
144
+ // Validate request with appropriate Zod schema
145
+ // If request has a `type` field, use discriminatedUnion schema (5-type)
146
+ // Otherwise, use legacy SendTransactionRequestSchema (backward compat)
147
+ const req = ctx.request;
148
+ if ('type' in req && req.type) {
149
+ TransactionRequestSchema.parse(req);
150
+ }
151
+ else {
152
+ SendTransactionRequestSchema.parse(req);
153
+ }
154
+ // Determine transaction type from request
155
+ const txType = ('type' in req && req.type) ? req.type : 'TRANSFER';
156
+ // Generate transaction ID
157
+ ctx.txId = generateId();
158
+ // INSERT PENDING transaction into DB
159
+ const now = new Date(Math.floor(Date.now() / 1000) * 1000);
160
+ // Extract common and type-specific fields for DB INSERT
161
+ const amount = 'amount' in req ? req.amount : undefined;
162
+ const toAddress = 'to' in req ? req.to : undefined;
163
+ await ctx.db.insert(transactions).values({
164
+ id: ctx.txId,
165
+ walletId: ctx.walletId,
166
+ chain: ctx.wallet.chain,
167
+ network: ctx.resolvedNetwork,
168
+ type: txType,
169
+ status: 'PENDING',
170
+ amount: amount ?? null,
171
+ toAddress: toAddress ?? null,
172
+ sessionId: ctx.sessionId ?? null,
173
+ createdAt: now,
174
+ });
175
+ // Fire-and-forget: notify TX_REQUESTED (never blocks pipeline)
176
+ // display_amount is empty at Stage 1 -- amountUsd not yet computed
177
+ void ctx.notificationService?.notify('TX_REQUESTED', ctx.walletId, {
178
+ amount: amount ?? '0',
179
+ to: toAddress ?? '',
180
+ type: txType,
181
+ display_amount: '',
182
+ }, { txId: ctx.txId });
183
+ // v1.6: emit wallet:activity TX_REQUESTED event
184
+ ctx.eventBus?.emit('wallet:activity', {
185
+ walletId: ctx.walletId,
186
+ activity: 'TX_REQUESTED',
187
+ details: { txId: ctx.txId },
188
+ timestamp: Math.floor(Date.now() / 1000),
189
+ });
190
+ }
191
+ // ---------------------------------------------------------------------------
192
+ // Stage 2: Auth (v1.1 passthrough)
193
+ // ---------------------------------------------------------------------------
194
+ export async function stage2Auth(_ctx) {
195
+ // sessionId is set on PipelineContext by the route handler from Hono c.get('sessionId').
196
+ // In v1.2 this stage validates session is still active.
197
+ // For now, the sessionAuth middleware already validated the JWT and set sessionId.
198
+ }
199
+ // ---------------------------------------------------------------------------
200
+ // Stage 3: Policy evaluation
201
+ // ---------------------------------------------------------------------------
202
+ export async function stage3Policy(ctx) {
203
+ let evaluation;
204
+ // Determine transaction type from request
205
+ const req = ctx.request;
206
+ const txType = ('type' in req && req.type) ? req.type : 'TRANSFER';
207
+ // Build type-specific TransactionParam (hoisted for notification use)
208
+ const txParam = buildTransactionParam(req, txType, ctx.wallet.chain);
209
+ txParam.network = ctx.resolvedNetwork;
210
+ // [Phase 127] Oracle HTTP 호출 (evaluateAndReserve 진입 전 완료)
211
+ let priceResult;
212
+ if (ctx.priceOracle) {
213
+ priceResult = await resolveEffectiveAmountUsd(req, txType, ctx.wallet.chain, ctx.priceOracle);
214
+ }
215
+ // BATCH type uses evaluateBatch (2-stage policy evaluation)
216
+ if (txType === 'BATCH' && ctx.policyEngine instanceof DatabasePolicyEngine) {
217
+ const batchReq = req;
218
+ // Classify each instruction and build TransactionParam array
219
+ const params = batchReq.instructions.map((instr) => {
220
+ let instrType = 'TRANSFER';
221
+ if ('spender' in instr)
222
+ instrType = 'APPROVE';
223
+ else if ('token' in instr)
224
+ instrType = 'TOKEN_TRANSFER';
225
+ else if ('programId' in instr || 'calldata' in instr)
226
+ instrType = 'CONTRACT_CALL';
227
+ return {
228
+ type: instrType,
229
+ amount: 'amount' in instr ? instr.amount ?? '0' : '0',
230
+ toAddress: 'to' in instr ? instr.to ?? '' : '',
231
+ chain: ctx.wallet.chain,
232
+ network: ctx.resolvedNetwork,
233
+ tokenAddress: 'token' in instr ? instr.token?.address : undefined,
234
+ contractAddress: instrType === 'CONTRACT_CALL' ? ('to' in instr ? instr.to : undefined) : undefined,
235
+ selector: 'calldata' in instr ? instr.calldata?.slice(0, 10) : undefined,
236
+ spenderAddress: 'spender' in instr ? instr.spender : undefined,
237
+ approveAmount: instrType === 'APPROVE' && 'amount' in instr ? instr.amount : undefined,
238
+ };
239
+ });
240
+ // evaluateBatch에 batchUsdAmount 전달 (Phase 127)
241
+ const batchUsdAmount = priceResult?.type === 'success' ? priceResult.usdAmount : undefined;
242
+ evaluation = await ctx.policyEngine.evaluateBatch(ctx.walletId, params, batchUsdAmount);
243
+ }
244
+ else {
245
+ // evaluateAndReserve에 usdAmount 전달 (Phase 127)
246
+ const usdAmount = priceResult?.type === 'success' ? priceResult.usdAmount : undefined;
247
+ // Use evaluateAndReserve for TOCTOU-safe evaluation when DatabasePolicyEngine + sqlite available
248
+ if (ctx.policyEngine instanceof DatabasePolicyEngine && ctx.sqlite) {
249
+ evaluation = ctx.policyEngine.evaluateAndReserve(ctx.walletId, txParam, ctx.txId, usdAmount);
250
+ }
251
+ else {
252
+ evaluation = await ctx.policyEngine.evaluate(ctx.walletId, txParam);
253
+ }
254
+ }
255
+ if (!evaluation.allowed) {
256
+ // Update tx status to CANCELLED (REJECTED not in TRANSACTION_STATUSES enum)
257
+ await ctx.db
258
+ .update(transactions)
259
+ .set({ status: 'CANCELLED', error: evaluation.reason ?? 'Policy denied' })
260
+ .where(eq(transactions.id, ctx.txId));
261
+ // Fire-and-forget: notify POLICY_VIOLATION (never blocks pipeline)
262
+ void ctx.notificationService?.notify('POLICY_VIOLATION', ctx.walletId, {
263
+ reason: evaluation.reason ?? 'Policy denied',
264
+ amount: getRequestAmount(ctx.request),
265
+ to: getRequestTo(ctx.request),
266
+ policyType: extractPolicyType(evaluation.reason),
267
+ tokenAddress: txParam.tokenAddress ?? '',
268
+ contractAddress: txParam.contractAddress ?? '',
269
+ adminLink: '/admin/policies',
270
+ }, { txId: ctx.txId });
271
+ throw new WAIaaSError('POLICY_DENIED', {
272
+ message: evaluation.reason ?? 'Transaction denied by policy',
273
+ });
274
+ }
275
+ let tier = evaluation.tier;
276
+ let downgraded = false;
277
+ // [Phase 127] PriceResult에 따른 후처리
278
+ if (priceResult?.type === 'notListed') {
279
+ // 감사 로그: UNLISTED_TOKEN_TRANSFER
280
+ await ctx.db.insert(auditLog).values({
281
+ timestamp: new Date(Math.floor(Date.now() / 1000) * 1000),
282
+ eventType: 'UNLISTED_TOKEN_TRANSFER',
283
+ actor: ctx.sessionId ?? 'system',
284
+ walletId: ctx.walletId,
285
+ txId: ctx.txId,
286
+ details: JSON.stringify({
287
+ tokenAddress: priceResult.tokenAddress,
288
+ chain: priceResult.chain,
289
+ failedCount: priceResult.failedCount,
290
+ }),
291
+ severity: 'warning',
292
+ });
293
+ // 최소 NOTIFY 격상 (evaluation tier와 NOTIFY 중 보수적)
294
+ const TIER_ORDER = ['INSTANT', 'NOTIFY', 'DELAY', 'APPROVAL'];
295
+ const currentIdx = TIER_ORDER.indexOf(tier);
296
+ const notifyIdx = TIER_ORDER.indexOf('NOTIFY');
297
+ if (currentIdx < notifyIdx) {
298
+ tier = 'NOTIFY';
299
+ }
300
+ // CoinGecko 키 미설정 + 최초 1회 힌트
301
+ const cacheKey = `${priceResult.chain}:${priceResult.tokenAddress}`;
302
+ const coingeckoKey = ctx.settingsService?.get('oracle.coingecko_api_key');
303
+ const shouldShowHint = !coingeckoKey && !hintedTokens.has(cacheKey);
304
+ if (shouldShowHint) {
305
+ hintedTokens.add(cacheKey);
306
+ }
307
+ // 가격 불명 토큰 알림 발송 (allowed=true인 상태에서도 notListed는 발생)
308
+ const hint = shouldShowHint
309
+ ? 'CoinGecko API 키를 설정하면 이 토큰의 USD 가격을 조회할 수 있습니다. Admin Settings > Oracle에서 설정하세요.'
310
+ : undefined;
311
+ const notifyVars = {
312
+ amount: getRequestAmount(ctx.request),
313
+ to: getRequestTo(ctx.request),
314
+ reason: `가격 불명 토큰 (${priceResult.tokenAddress}) -- 최소 NOTIFY 격상`,
315
+ policyType: 'SPENDING_LIMIT',
316
+ };
317
+ if (hint)
318
+ notifyVars.hint = hint;
319
+ void ctx.notificationService?.notify('POLICY_VIOLATION', ctx.walletId, notifyVars, { txId: ctx.txId });
320
+ }
321
+ // oracleDown: 아무것도 하지 않음 -- 네이티브 금액 기준 tier가 이미 설정됨
322
+ // Check for APPROVAL -> DELAY downgrade when no owner registered
323
+ if (tier === 'APPROVAL') {
324
+ const walletRow = await ctx.db.select().from(wallets).where(eq(wallets.id, ctx.walletId)).get();
325
+ if (walletRow) {
326
+ const result = downgradeIfNoOwner({
327
+ ownerAddress: walletRow.ownerAddress ?? null,
328
+ ownerVerified: walletRow.ownerVerified ?? false,
329
+ }, tier);
330
+ tier = result.tier;
331
+ downgraded = result.downgraded;
332
+ }
333
+ }
334
+ // Set tier and metadata on context
335
+ ctx.tier = tier;
336
+ ctx.downgraded = downgraded;
337
+ if (evaluation.delaySeconds !== undefined) {
338
+ ctx.delaySeconds = evaluation.delaySeconds;
339
+ }
340
+ // [Phase 139] Cache amountUsd on context for Stage 5/6 display_amount
341
+ const stageAmountUsd = priceResult?.type === 'success' ? priceResult.usdAmount : undefined;
342
+ ctx.amountUsd = stageAmountUsd;
343
+ // [Phase 139] Resolve display amount for notifications
344
+ const displayAmount = await resolveDisplayAmount(stageAmountUsd ?? null, ctx.settingsService, ctx.forexRateService);
345
+ // [Phase 136] Cumulative spending warning notification (80% threshold)
346
+ if (evaluation.cumulativeWarning) {
347
+ const w = evaluation.cumulativeWarning;
348
+ void ctx.notificationService?.notify('CUMULATIVE_LIMIT_WARNING', ctx.walletId, {
349
+ type: w.type,
350
+ spent: String(w.spent.toFixed(2)),
351
+ limit: String(w.limit.toFixed(2)),
352
+ ratio: String(Math.round(w.ratio * 100)),
353
+ display_amount: displayAmount,
354
+ }, { txId: ctx.txId });
355
+ }
356
+ // [Phase 136] APPROVAL tier notification with reason
357
+ if (tier === 'APPROVAL' && !downgraded) {
358
+ const reason = evaluation.approvalReason ?? 'per_tx';
359
+ void ctx.notificationService?.notify('TX_APPROVAL_REQUIRED', ctx.walletId, {
360
+ amount: getRequestAmount(ctx.request),
361
+ to: getRequestTo(ctx.request),
362
+ reason,
363
+ display_amount: displayAmount,
364
+ }, { txId: ctx.txId });
365
+ }
366
+ // Update DB with tier
367
+ await ctx.db
368
+ .update(transactions)
369
+ .set({ tier })
370
+ .where(eq(transactions.id, ctx.txId));
371
+ }
372
+ // ---------------------------------------------------------------------------
373
+ // Stage 4: Wait (DELAY/APPROVAL branching, INSTANT/NOTIFY passthrough)
374
+ // ---------------------------------------------------------------------------
375
+ export async function stage4Wait(ctx) {
376
+ const tier = ctx.tier;
377
+ // INSTANT and NOTIFY: pass through to stage5
378
+ if (tier === 'INSTANT' || tier === 'NOTIFY') {
379
+ return;
380
+ }
381
+ // DELAY: queue with cooldown, halt pipeline
382
+ if (tier === 'DELAY') {
383
+ if (!ctx.delayQueue) {
384
+ // Fallback: if no DelayQueue, treat as INSTANT (backward compat)
385
+ return;
386
+ }
387
+ const delaySeconds = ctx.delaySeconds
388
+ ?? ctx.config?.policy_defaults_delay_seconds
389
+ ?? 60;
390
+ ctx.delayQueue.queueDelay(ctx.txId, delaySeconds);
391
+ // Halt pipeline -- transaction will be picked up by processExpired worker
392
+ throw new WAIaaSError('PIPELINE_HALTED', {
393
+ message: `Transaction ${ctx.txId} queued for ${delaySeconds}s delay`,
394
+ });
395
+ }
396
+ // APPROVAL: create pending approval, halt pipeline
397
+ if (tier === 'APPROVAL') {
398
+ if (!ctx.approvalWorkflow) {
399
+ // Fallback: if no ApprovalWorkflow, treat as INSTANT (backward compat)
400
+ return;
401
+ }
402
+ ctx.approvalWorkflow.requestApproval(ctx.txId);
403
+ // v1.6.1: fire-and-forget WC signing request (non-blocking)
404
+ if (ctx.wcSigningBridge) {
405
+ void ctx.wcSigningBridge.requestSignature(ctx.walletId, ctx.txId, ctx.wallet.chain);
406
+ }
407
+ // Halt pipeline -- transaction will be picked up by approve/reject/expire
408
+ throw new WAIaaSError('PIPELINE_HALTED', {
409
+ message: `Transaction ${ctx.txId} queued for owner approval`,
410
+ });
411
+ }
412
+ }
413
+ // ---------------------------------------------------------------------------
414
+ // Helper: buildByType -- route to correct adapter method based on request.type
415
+ // ---------------------------------------------------------------------------
416
+ /**
417
+ * Build unsigned transaction by dispatching to the correct IChainAdapter method
418
+ * based on request.type (TRANSFER/TOKEN_TRANSFER/CONTRACT_CALL/APPROVE/BATCH).
419
+ */
420
+ async function buildByType(adapter, request, walletPublicKey) {
421
+ const type = ('type' in request && request.type) || 'TRANSFER';
422
+ switch (type) {
423
+ case 'TRANSFER': {
424
+ return adapter.buildTransaction({
425
+ from: walletPublicKey,
426
+ to: getRequestTo(request),
427
+ amount: BigInt(getRequestAmount(request)),
428
+ memo: getRequestMemo(request),
429
+ });
430
+ }
431
+ case 'TOKEN_TRANSFER': {
432
+ const req = request;
433
+ return adapter.buildTokenTransfer({
434
+ from: walletPublicKey,
435
+ to: req.to,
436
+ amount: BigInt(req.amount),
437
+ token: req.token,
438
+ memo: req.memo,
439
+ });
440
+ }
441
+ case 'CONTRACT_CALL': {
442
+ const req = request;
443
+ return adapter.buildContractCall({
444
+ from: walletPublicKey,
445
+ to: req.to,
446
+ calldata: req.calldata,
447
+ abi: req.abi,
448
+ value: req.value ? BigInt(req.value) : undefined,
449
+ programId: req.programId,
450
+ instructionData: req.instructionData
451
+ ? Buffer.from(req.instructionData, 'base64')
452
+ : undefined,
453
+ accounts: req.accounts,
454
+ });
455
+ }
456
+ case 'APPROVE': {
457
+ const req = request;
458
+ return adapter.buildApprove({
459
+ from: walletPublicKey,
460
+ spender: req.spender,
461
+ token: req.token,
462
+ amount: BigInt(req.amount),
463
+ });
464
+ }
465
+ case 'BATCH': {
466
+ const req = request;
467
+ return adapter.buildBatch({
468
+ from: walletPublicKey,
469
+ instructions: req.instructions.map((instr) => {
470
+ // Classify by field presence (same logic as classifyInstruction in Phase 80)
471
+ if ('spender' in instr) {
472
+ const a = instr;
473
+ return {
474
+ from: walletPublicKey,
475
+ spender: a.spender,
476
+ token: a.token,
477
+ amount: BigInt(a.amount),
478
+ };
479
+ }
480
+ if ('token' in instr) {
481
+ const t = instr;
482
+ return {
483
+ from: walletPublicKey,
484
+ to: t.to,
485
+ amount: BigInt(t.amount),
486
+ token: t.token,
487
+ memo: t.memo,
488
+ };
489
+ }
490
+ if ('programId' in instr || 'calldata' in instr) {
491
+ const c = instr;
492
+ return {
493
+ from: walletPublicKey,
494
+ to: c.to,
495
+ calldata: c.calldata,
496
+ programId: c.programId,
497
+ instructionData: c.instructionData
498
+ ? Buffer.from(c.instructionData, 'base64')
499
+ : undefined,
500
+ accounts: c.accounts,
501
+ value: c.value ? BigInt(c.value) : undefined,
502
+ };
503
+ }
504
+ // Default: TRANSFER instruction
505
+ const tr = instr;
506
+ return {
507
+ from: walletPublicKey,
508
+ to: tr.to,
509
+ amount: BigInt(tr.amount),
510
+ memo: tr.memo,
511
+ };
512
+ }),
513
+ });
514
+ }
515
+ default:
516
+ throw new WAIaaSError('CHAIN_ERROR', {
517
+ message: `Unknown transaction type: ${type}`,
518
+ });
519
+ }
520
+ }
521
+ // ---------------------------------------------------------------------------
522
+ // Stage 5: On-chain execution (CONC-01 retry loop)
523
+ // ---------------------------------------------------------------------------
524
+ /**
525
+ * Stage 5: Build -> Simulate -> Sign -> Submit with CONC-01 retry logic.
526
+ *
527
+ * ChainError category-based retry:
528
+ * - PERMANENT: immediate FAILED, no retry
529
+ * - TRANSIENT: exponential backoff (1s, 2s, 4s), max 3 retries (retryCount >= 3 guard)
530
+ * - STALE: rebuild from Stage 5a, max 1 (retryCount >= 1 guard)
531
+ *
532
+ * retryCount is shared between TRANSIENT and STALE to limit total retry count.
533
+ * Total attempts: initial 1 + up to 3 retries = 4 max.
534
+ */
535
+ export async function stage5Execute(ctx) {
536
+ const reqAmount = getRequestAmount(ctx.request);
537
+ const reqTo = getRequestTo(ctx.request);
538
+ // [Phase 139] Resolve display amount once for all Stage 5 notifications
539
+ const displayAmount = await resolveDisplayAmount(ctx.amountUsd ?? null, ctx.settingsService, ctx.forexRateService);
540
+ let retryCount = 0;
541
+ // Outer buildLoop: STALE errors return here to rebuild from Stage 5a
542
+ buildLoop: while (true) {
543
+ try {
544
+ // Stage 5a: Build unsigned transaction (type-routed)
545
+ ctx.unsignedTx = await buildByType(ctx.adapter, ctx.request, ctx.wallet.publicKey);
546
+ // Stage 5b: Simulate
547
+ const simResult = await ctx.adapter.simulateTransaction(ctx.unsignedTx);
548
+ if (!simResult.success) {
549
+ await ctx.db
550
+ .update(transactions)
551
+ .set({ status: 'FAILED', error: simResult.error ?? 'Simulation failed' })
552
+ .where(eq(transactions.id, ctx.txId));
553
+ // Fire-and-forget: notify TX_FAILED on simulation failure
554
+ void ctx.notificationService?.notify('TX_FAILED', ctx.walletId, {
555
+ reason: simResult.error ?? 'Simulation failed',
556
+ amount: reqAmount,
557
+ display_amount: displayAmount,
558
+ }, { txId: ctx.txId });
559
+ // v1.6: emit transaction:failed event (simulation failure)
560
+ ctx.eventBus?.emit('transaction:failed', {
561
+ walletId: ctx.walletId,
562
+ txId: ctx.txId,
563
+ error: simResult.error ?? 'Simulation failed',
564
+ network: ctx.resolvedNetwork,
565
+ type: ('type' in ctx.request && ctx.request.type) ? ctx.request.type : 'TRANSFER',
566
+ timestamp: Math.floor(Date.now() / 1000),
567
+ });
568
+ throw new WAIaaSError('SIMULATION_FAILED', {
569
+ message: simResult.error ?? 'Transaction simulation failed',
570
+ });
571
+ }
572
+ // Stage 5c: Decrypt private key, sign
573
+ // CRITICAL: key MUST be released in finally block
574
+ let privateKey = null;
575
+ try {
576
+ privateKey = await ctx.keyStore.decryptPrivateKey(ctx.walletId, ctx.masterPassword);
577
+ ctx.signedTx = await ctx.adapter.signTransaction(ctx.unsignedTx, privateKey);
578
+ }
579
+ finally {
580
+ if (privateKey) {
581
+ ctx.keyStore.releaseKey(privateKey);
582
+ }
583
+ }
584
+ // Stage 5d: Submit
585
+ ctx.submitResult = await ctx.adapter.submitTransaction(ctx.signedTx);
586
+ // Success: Update DB SUBMITTED + txHash
587
+ await ctx.db
588
+ .update(transactions)
589
+ .set({ status: 'SUBMITTED', txHash: ctx.submitResult.txHash })
590
+ .where(eq(transactions.id, ctx.txId));
591
+ // Fire-and-forget: notify TX_SUBMITTED
592
+ void ctx.notificationService?.notify('TX_SUBMITTED', ctx.walletId, {
593
+ txHash: ctx.submitResult.txHash,
594
+ amount: reqAmount,
595
+ to: reqTo,
596
+ display_amount: displayAmount,
597
+ }, { txId: ctx.txId });
598
+ // v1.6: emit wallet:activity TX_SUBMITTED event
599
+ ctx.eventBus?.emit('wallet:activity', {
600
+ walletId: ctx.walletId,
601
+ activity: 'TX_SUBMITTED',
602
+ details: { txId: ctx.txId, txHash: ctx.submitResult.txHash },
603
+ timestamp: Math.floor(Date.now() / 1000),
604
+ });
605
+ return; // Success -- exit the loop
606
+ }
607
+ catch (err) {
608
+ // Non-ChainError: rethrow as-is (WAIaaSError, validation errors, etc.)
609
+ if (!(err instanceof ChainError)) {
610
+ throw err;
611
+ }
612
+ // ChainError: category-based retry logic
613
+ switch (err.category) {
614
+ case 'PERMANENT': {
615
+ // Immediate failure, no retry
616
+ await ctx.db
617
+ .update(transactions)
618
+ .set({ status: 'FAILED', error: err.message })
619
+ .where(eq(transactions.id, ctx.txId));
620
+ // Fire-and-forget: notify TX_FAILED
621
+ void ctx.notificationService?.notify('TX_FAILED', ctx.walletId, {
622
+ reason: err.message,
623
+ amount: reqAmount,
624
+ display_amount: displayAmount,
625
+ }, { txId: ctx.txId });
626
+ // v1.6: emit transaction:failed event (permanent chain error)
627
+ ctx.eventBus?.emit('transaction:failed', {
628
+ walletId: ctx.walletId,
629
+ txId: ctx.txId,
630
+ error: err.message,
631
+ network: ctx.resolvedNetwork,
632
+ type: ('type' in ctx.request && ctx.request.type) ? ctx.request.type : 'TRANSFER',
633
+ timestamp: Math.floor(Date.now() / 1000),
634
+ });
635
+ throw new WAIaaSError('CHAIN_ERROR', {
636
+ message: err.message,
637
+ cause: err,
638
+ });
639
+ }
640
+ case 'TRANSIENT': {
641
+ if (retryCount >= 3) {
642
+ // Max retries exhausted
643
+ await ctx.db
644
+ .update(transactions)
645
+ .set({ status: 'FAILED', error: `${err.code} (max retries exceeded)` })
646
+ .where(eq(transactions.id, ctx.txId));
647
+ // Fire-and-forget: notify TX_FAILED
648
+ void ctx.notificationService?.notify('TX_FAILED', ctx.walletId, {
649
+ reason: `${err.code} (max retries exceeded)`,
650
+ amount: reqAmount,
651
+ display_amount: displayAmount,
652
+ }, { txId: ctx.txId });
653
+ // v1.6: emit transaction:failed event (transient max retries)
654
+ ctx.eventBus?.emit('transaction:failed', {
655
+ walletId: ctx.walletId,
656
+ txId: ctx.txId,
657
+ error: `${err.code} (max retries exceeded)`,
658
+ network: ctx.resolvedNetwork,
659
+ type: ('type' in ctx.request && ctx.request.type) ? ctx.request.type : 'TRANSFER',
660
+ timestamp: Math.floor(Date.now() / 1000),
661
+ });
662
+ throw new WAIaaSError('CHAIN_ERROR', {
663
+ message: `${err.message} (max retries exceeded)`,
664
+ cause: err,
665
+ });
666
+ }
667
+ // Exponential backoff: 1s, 2s, 4s
668
+ await sleep(1000 * Math.pow(2, retryCount));
669
+ retryCount++;
670
+ continue buildLoop; // Retry from Stage 5a (rebuild)
671
+ }
672
+ case 'STALE': {
673
+ if (retryCount >= 1) {
674
+ // Stale retry exhausted (shared retryCount)
675
+ await ctx.db
676
+ .update(transactions)
677
+ .set({ status: 'FAILED', error: `${err.code} (stale retry exhausted)` })
678
+ .where(eq(transactions.id, ctx.txId));
679
+ // Fire-and-forget: notify TX_FAILED
680
+ void ctx.notificationService?.notify('TX_FAILED', ctx.walletId, {
681
+ reason: `${err.code} (stale retry exhausted)`,
682
+ amount: reqAmount,
683
+ display_amount: displayAmount,
684
+ }, { txId: ctx.txId });
685
+ // v1.6: emit transaction:failed event (stale retry exhausted)
686
+ ctx.eventBus?.emit('transaction:failed', {
687
+ walletId: ctx.walletId,
688
+ txId: ctx.txId,
689
+ error: `${err.code} (stale retry exhausted)`,
690
+ network: ctx.resolvedNetwork,
691
+ type: ('type' in ctx.request && ctx.request.type) ? ctx.request.type : 'TRANSFER',
692
+ timestamp: Math.floor(Date.now() / 1000),
693
+ });
694
+ throw new WAIaaSError('CHAIN_ERROR', {
695
+ message: `${err.message} (stale retry exhausted)`,
696
+ cause: err,
697
+ });
698
+ }
699
+ // Rebuild from Stage 5a with new blockhash/nonce
700
+ retryCount++;
701
+ continue buildLoop;
702
+ }
703
+ default: {
704
+ // Unknown category: treat as permanent
705
+ await ctx.db
706
+ .update(transactions)
707
+ .set({ status: 'FAILED', error: err.message })
708
+ .where(eq(transactions.id, ctx.txId));
709
+ throw new WAIaaSError('CHAIN_ERROR', {
710
+ message: err.message,
711
+ cause: err,
712
+ });
713
+ }
714
+ }
715
+ }
716
+ }
717
+ }
718
+ // ---------------------------------------------------------------------------
719
+ // Stage 6: Confirmation wait
720
+ // ---------------------------------------------------------------------------
721
+ export async function stage6Confirm(ctx) {
722
+ const reqAmount = getRequestAmount(ctx.request);
723
+ const reqTo = getRequestTo(ctx.request);
724
+ // [Phase 139] Resolve display amount for Stage 6 notifications
725
+ const displayAmount = await resolveDisplayAmount(ctx.amountUsd ?? null, ctx.settingsService, ctx.forexRateService);
726
+ const result = await ctx.adapter.waitForConfirmation(ctx.submitResult.txHash, 30_000);
727
+ if (result.status === 'confirmed' || result.status === 'finalized') {
728
+ // On-chain confirmed
729
+ const executedAt = new Date(Math.floor(Date.now() / 1000) * 1000);
730
+ await ctx.db
731
+ .update(transactions)
732
+ .set({ status: 'CONFIRMED', executedAt })
733
+ .where(eq(transactions.id, ctx.txId));
734
+ // Fire-and-forget: notify TX_CONFIRMED (never blocks pipeline)
735
+ void ctx.notificationService?.notify('TX_CONFIRMED', ctx.walletId, {
736
+ txHash: ctx.submitResult.txHash,
737
+ amount: reqAmount,
738
+ to: reqTo,
739
+ display_amount: displayAmount,
740
+ }, { txId: ctx.txId });
741
+ // v1.6: emit transaction:completed event
742
+ ctx.eventBus?.emit('transaction:completed', {
743
+ walletId: ctx.walletId,
744
+ txId: ctx.txId,
745
+ txHash: ctx.submitResult.txHash,
746
+ amount: getRequestAmount(ctx.request),
747
+ network: ctx.resolvedNetwork,
748
+ type: ('type' in ctx.request && ctx.request.type) ? ctx.request.type : 'TRANSFER',
749
+ timestamp: Math.floor(Date.now() / 1000),
750
+ });
751
+ }
752
+ else if (result.status === 'failed') {
753
+ // On-chain revert
754
+ await ctx.db
755
+ .update(transactions)
756
+ .set({ status: 'FAILED', error: 'Transaction reverted on-chain' })
757
+ .where(eq(transactions.id, ctx.txId));
758
+ // Fire-and-forget: notify TX_FAILED on on-chain revert (never blocks pipeline)
759
+ void ctx.notificationService?.notify('TX_FAILED', ctx.walletId, {
760
+ reason: 'Transaction reverted on-chain',
761
+ amount: reqAmount,
762
+ display_amount: displayAmount,
763
+ }, { txId: ctx.txId });
764
+ // v1.6: emit transaction:failed event (on-chain revert)
765
+ ctx.eventBus?.emit('transaction:failed', {
766
+ walletId: ctx.walletId,
767
+ txId: ctx.txId,
768
+ error: 'Transaction reverted on-chain',
769
+ network: ctx.resolvedNetwork,
770
+ type: ('type' in ctx.request && ctx.request.type) ? ctx.request.type : 'TRANSFER',
771
+ timestamp: Math.floor(Date.now() / 1000),
772
+ });
773
+ throw new WAIaaSError('CHAIN_ERROR', {
774
+ message: 'Transaction reverted on-chain',
775
+ });
776
+ }
777
+ else {
778
+ // status === 'submitted': still pending, NOT failed
779
+ // Keep SUBMITTED status (already set by Stage 5)
780
+ // Do NOT overwrite to FAILED -- tx may confirm later
781
+ // No notification: no state change occurred
782
+ }
783
+ }
784
+ //# sourceMappingURL=stages.js.map