tapimo 0.12.0 → 0.14.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 (398) hide show
  1. package/dist/App.d.ts +11333 -9563
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +39 -3
  4. package/dist/App.js.map +1 -1
  5. package/dist/Scope.d.ts +2 -0
  6. package/dist/Scope.d.ts.map +1 -1
  7. package/dist/Scope.js +17 -0
  8. package/dist/Scope.js.map +1 -1
  9. package/dist/Webhooks.js +2 -2
  10. package/dist/Webhooks.js.map +1 -1
  11. package/dist/admin/App.d.ts +1064 -924
  12. package/dist/admin/App.d.ts.map +1 -1
  13. package/dist/admin/apps/api-keys.d.ts +80 -0
  14. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  15. package/dist/admin/apps/api-keys.js +54 -0
  16. package/dist/admin/apps/api-keys.js.map +1 -1
  17. package/dist/admin/apps/earn-vaults.d.ts +63 -15
  18. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  19. package/dist/admin/apps/earn-vaults.js +2 -1
  20. package/dist/admin/apps/earn-vaults.js.map +1 -1
  21. package/dist/admin/apps/organizations.d.ts +92 -3
  22. package/dist/admin/apps/organizations.d.ts.map +1 -1
  23. package/dist/admin/apps/organizations.js +69 -7
  24. package/dist/admin/apps/organizations.js.map +1 -1
  25. package/dist/admin/apps/verified-tokens.d.ts +7 -7
  26. package/dist/admin/ui.generated.d.ts +1 -1
  27. package/dist/admin/ui.generated.d.ts.map +1 -1
  28. package/dist/admin/ui.generated.js +151 -151
  29. package/dist/admin/ui.generated.js.map +1 -1
  30. package/dist/apps/Zones.d.ts +28 -28
  31. package/dist/apps/Zones.js +7 -7
  32. package/dist/apps/data/App.d.ts +2909 -2523
  33. package/dist/apps/data/App.d.ts.map +1 -1
  34. package/dist/apps/data/App.js +26 -21
  35. package/dist/apps/data/App.js.map +1 -1
  36. package/dist/apps/data/ZoneSelection.d.ts +8 -8
  37. package/dist/apps/data/ZoneSelection.d.ts.map +1 -1
  38. package/dist/apps/data/ZoneSelection.js +1 -1
  39. package/dist/apps/data/ZoneSelection.js.map +1 -1
  40. package/dist/apps/data/routes/activities.d.ts +588 -584
  41. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  42. package/dist/apps/data/routes/activities.js +1561 -1239
  43. package/dist/apps/data/routes/activities.js.map +1 -1
  44. package/dist/apps/data/routes/addresses.d.ts +22 -22
  45. package/dist/apps/data/routes/balances.d.ts +26 -26
  46. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  47. package/dist/apps/data/routes/balances.js +43 -16
  48. package/dist/apps/data/routes/balances.js.map +1 -1
  49. package/dist/apps/data/routes/blocks.d.ts +44 -44
  50. package/dist/apps/data/routes/blocks.d.ts.map +1 -1
  51. package/dist/apps/data/routes/blocks.js +21 -11
  52. package/dist/apps/data/routes/blocks.js.map +1 -1
  53. package/dist/apps/data/routes/coingecko.d.ts +3 -3
  54. package/dist/apps/data/routes/earn.d.ts +201 -25
  55. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  56. package/dist/apps/data/routes/earn.js +434 -75
  57. package/dist/apps/data/routes/earn.js.map +1 -1
  58. package/dist/apps/data/routes/exchanges.d.ts +160 -145
  59. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  60. package/dist/apps/data/routes/exchanges.js +180 -114
  61. package/dist/apps/data/routes/exchanges.js.map +1 -1
  62. package/dist/apps/data/routes/fee-amm.d.ts +2 -2
  63. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  64. package/dist/apps/data/routes/fee-amm.js +18 -19
  65. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  66. package/dist/apps/data/routes/receipts.d.ts +155 -55
  67. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  68. package/dist/apps/data/routes/receipts.js +28 -10
  69. package/dist/apps/data/routes/receipts.js.map +1 -1
  70. package/dist/apps/data/routes/tokenlist.d.ts +13 -13
  71. package/dist/apps/data/routes/tokens.d.ts +5 -5
  72. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  73. package/dist/apps/data/routes/tokens.js +51 -20
  74. package/dist/apps/data/routes/tokens.js.map +1 -1
  75. package/dist/apps/data/routes/transactions.d.ts +7 -2
  76. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  77. package/dist/apps/data/routes/transactions.js +37 -17
  78. package/dist/apps/data/routes/transactions.js.map +1 -1
  79. package/dist/apps/data/routes/transfers.d.ts +13 -13
  80. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  81. package/dist/apps/data/routes/transfers.js +18 -12
  82. package/dist/apps/data/routes/transfers.js.map +1 -1
  83. package/dist/apps/data/routes/valuation.d.ts +31 -31
  84. package/dist/apps/data/routes/valuation.d.ts.map +1 -1
  85. package/dist/apps/data/routes/valuation.js +12 -7
  86. package/dist/apps/data/routes/valuation.js.map +1 -1
  87. package/dist/apps/data/routes/verified-tokens.d.ts +8 -8
  88. package/dist/apps/data/routes/webhooks.d.ts +816 -113
  89. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  90. package/dist/apps/data/routes/webhooks.js +47 -5
  91. package/dist/apps/data/routes/webhooks.js.map +1 -1
  92. package/dist/apps/data/routes/zones.d.ts +14 -14
  93. package/dist/apps/data/routes/zones.js +1 -1
  94. package/dist/apps/funding/App.d.ts +466 -44
  95. package/dist/apps/funding/App.d.ts.map +1 -1
  96. package/dist/apps/funding/App.js +1 -1
  97. package/dist/apps/funding/App.js.map +1 -1
  98. package/dist/apps/funding/routes/deposit-addresses.d.ts +17 -17
  99. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  100. package/dist/apps/funding/routes/deposit-addresses.js +17 -12
  101. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  102. package/dist/apps/funding/routes/transfers.d.ts +650 -57
  103. package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
  104. package/dist/apps/funding/routes/transfers.js +238 -24
  105. package/dist/apps/funding/routes/transfers.js.map +1 -1
  106. package/dist/apps/management/App.d.ts +5120 -4152
  107. package/dist/apps/management/App.d.ts.map +1 -1
  108. package/dist/apps/management/Billing.d.ts +1 -1
  109. package/dist/apps/management/Billing.d.ts.map +1 -1
  110. package/dist/apps/management/Billing.js +17 -1
  111. package/dist/apps/management/Billing.js.map +1 -1
  112. package/dist/apps/management/routes/api-keys.d.ts +632 -81
  113. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  114. package/dist/apps/management/routes/api-keys.js +236 -4
  115. package/dist/apps/management/routes/api-keys.js.map +1 -1
  116. package/dist/apps/management/routes/billing.d.ts +76 -76
  117. package/dist/apps/management/routes/faucet.d.ts +6 -6
  118. package/dist/apps/management/routes/invitations.d.ts +24 -24
  119. package/dist/apps/management/routes/invite-links.d.ts +4 -4
  120. package/dist/apps/management/routes/members.d.ts +16 -16
  121. package/dist/apps/management/routes/orgs.d.ts +20 -20
  122. package/dist/apps/management/routes/projects.d.ts +4 -4
  123. package/dist/apps/management/routes/usage.d.ts +8 -8
  124. package/dist/apps/management/routes/verified-token-requests.d.ts +17 -17
  125. package/dist/apps/management/routes/webhooks.d.ts +675 -25
  126. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  127. package/dist/apps/management/routes/webhooks.js +21 -21
  128. package/dist/apps/management/routes/webhooks.js.map +1 -1
  129. package/dist/apps/relay/App.d.ts.map +1 -1
  130. package/dist/apps/relay/App.js +115 -23
  131. package/dist/apps/relay/App.js.map +1 -1
  132. package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
  133. package/dist/apps/relay/Sponsorships.js +27 -1
  134. package/dist/apps/relay/Sponsorships.js.map +1 -1
  135. package/dist/db/Db.d.ts.map +1 -1
  136. package/dist/db/Db.js +34 -1
  137. package/dist/db/Db.js.map +1 -1
  138. package/dist/db/Schema.d.ts +11 -5
  139. package/dist/db/Schema.d.ts.map +1 -1
  140. package/dist/db/Schema.js +21 -3
  141. package/dist/db/Schema.js.map +1 -1
  142. package/dist/db/tables/fundingCatalog.d.ts +4 -2
  143. package/dist/db/tables/fundingCatalog.d.ts.map +1 -1
  144. package/dist/db/tables/fundingCatalog.js +5 -1
  145. package/dist/db/tables/fundingCatalog.js.map +1 -1
  146. package/dist/db/tables/fundingTransferTransactions.d.ts +38 -0
  147. package/dist/db/tables/fundingTransferTransactions.d.ts.map +1 -1
  148. package/dist/db/tables/fundingTransferTransactions.js +44 -3
  149. package/dist/db/tables/fundingTransferTransactions.js.map +1 -1
  150. package/dist/db/tables/fundingTransfers.d.ts +17 -0
  151. package/dist/db/tables/fundingTransfers.d.ts.map +1 -1
  152. package/dist/db/tables/fundingTransfers.js +21 -0
  153. package/dist/db/tables/fundingTransfers.js.map +1 -1
  154. package/dist/db/tables/organizations.d.ts +24 -0
  155. package/dist/db/tables/organizations.d.ts.map +1 -1
  156. package/dist/db/tables/organizations.js +27 -0
  157. package/dist/db/tables/organizations.js.map +1 -1
  158. package/dist/db/tables/projects.d.ts +25 -1
  159. package/dist/db/tables/projects.d.ts.map +1 -1
  160. package/dist/db/tables/projects.js +26 -0
  161. package/dist/db/tables/projects.js.map +1 -1
  162. package/dist/db/tables/sponsoredTransactions.d.ts +44 -0
  163. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  164. package/dist/db/tables/sponsoredTransactions.js +146 -13
  165. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  166. package/dist/db/tables/webhookSubscriptions.d.ts +10 -6
  167. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  168. package/dist/db/tables/webhookSubscriptions.js +9 -6
  169. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  170. package/dist/handlers/internal/utils.d.ts.map +1 -1
  171. package/dist/handlers/internal/utils.js +9 -0
  172. package/dist/handlers/internal/utils.js.map +1 -1
  173. package/dist/internal/Auth.d.ts +3 -1
  174. package/dist/internal/Auth.d.ts.map +1 -1
  175. package/dist/internal/Auth.js +6 -3
  176. package/dist/internal/Auth.js.map +1 -1
  177. package/dist/internal/EarnVaults.d.ts +3 -3
  178. package/dist/internal/EarnVaults.js +5 -5
  179. package/dist/internal/EarnVaults.js.map +1 -1
  180. package/dist/internal/Fetch.d.ts +23 -0
  181. package/dist/internal/Fetch.d.ts.map +1 -0
  182. package/dist/internal/Fetch.js +26 -0
  183. package/dist/internal/Fetch.js.map +1 -0
  184. package/dist/internal/Log.d.ts +4 -2
  185. package/dist/internal/Log.d.ts.map +1 -1
  186. package/dist/internal/Log.js +16 -3
  187. package/dist/internal/Log.js.map +1 -1
  188. package/dist/internal/OpenApi.d.ts +5 -3
  189. package/dist/internal/OpenApi.d.ts.map +1 -1
  190. package/dist/internal/OpenApi.js +13 -3
  191. package/dist/internal/OpenApi.js.map +1 -1
  192. package/dist/internal/Response.d.ts +1 -1
  193. package/dist/internal/Response.d.ts.map +1 -1
  194. package/dist/internal/Schema.d.ts +6 -3
  195. package/dist/internal/Schema.d.ts.map +1 -1
  196. package/dist/internal/Schema.js +8 -2
  197. package/dist/internal/Schema.js.map +1 -1
  198. package/dist/internal/Store.d.ts +16 -3
  199. package/dist/internal/Store.d.ts.map +1 -1
  200. package/dist/internal/Store.js +82 -16
  201. package/dist/internal/Store.js.map +1 -1
  202. package/dist/internal/Tidx.d.ts.map +1 -1
  203. package/dist/internal/Tidx.js +7 -2
  204. package/dist/internal/Tidx.js.map +1 -1
  205. package/dist/internal/Timeout.d.ts +36 -0
  206. package/dist/internal/Timeout.d.ts.map +1 -0
  207. package/dist/internal/Timeout.js +37 -0
  208. package/dist/internal/Timeout.js.map +1 -0
  209. package/dist/internal/Timing.d.ts +9 -0
  210. package/dist/internal/Timing.d.ts.map +1 -1
  211. package/dist/internal/Timing.js +7 -0
  212. package/dist/internal/Timing.js.map +1 -1
  213. package/dist/internal/Viem.d.ts +16 -1
  214. package/dist/internal/Viem.d.ts.map +1 -1
  215. package/dist/internal/Viem.js +12 -2
  216. package/dist/internal/Viem.js.map +1 -1
  217. package/dist/internal/WebhookDestination.d.ts.map +1 -1
  218. package/dist/internal/WebhookDestination.js +3 -0
  219. package/dist/internal/WebhookDestination.js.map +1 -1
  220. package/dist/internal/funding/Action.d.ts +9 -0
  221. package/dist/internal/funding/Action.d.ts.map +1 -1
  222. package/dist/internal/funding/Action.js +16 -8
  223. package/dist/internal/funding/Action.js.map +1 -1
  224. package/dist/internal/funding/Catalog.d.ts +9 -2
  225. package/dist/internal/funding/Catalog.d.ts.map +1 -1
  226. package/dist/internal/funding/Catalog.js +19 -8
  227. package/dist/internal/funding/Catalog.js.map +1 -1
  228. package/dist/internal/funding/DepositWebhook.d.ts.map +1 -1
  229. package/dist/internal/funding/DepositWebhook.js +2 -1
  230. package/dist/internal/funding/DepositWebhook.js.map +1 -1
  231. package/dist/internal/funding/Evidence.d.ts.map +1 -1
  232. package/dist/internal/funding/Evidence.js +2 -10
  233. package/dist/internal/funding/Evidence.js.map +1 -1
  234. package/dist/internal/funding/Provider.d.ts +108 -13
  235. package/dist/internal/funding/Provider.d.ts.map +1 -1
  236. package/dist/internal/funding/Provider.js +34 -8
  237. package/dist/internal/funding/Provider.js.map +1 -1
  238. package/dist/internal/funding/SourceObservation.d.ts.map +1 -1
  239. package/dist/internal/funding/SourceObservation.js +5 -7
  240. package/dist/internal/funding/SourceObservation.js.map +1 -1
  241. package/dist/internal/funding/Transfer.d.ts +114 -18
  242. package/dist/internal/funding/Transfer.d.ts.map +1 -1
  243. package/dist/internal/funding/Transfer.js +185 -55
  244. package/dist/internal/funding/Transfer.js.map +1 -1
  245. package/dist/internal/funding/TransferReconciliation.d.ts +52 -0
  246. package/dist/internal/funding/TransferReconciliation.d.ts.map +1 -0
  247. package/dist/internal/funding/TransferReconciliation.js +192 -0
  248. package/dist/internal/funding/TransferReconciliation.js.map +1 -0
  249. package/dist/internal/funding/TransferWebhook.d.ts +21 -0
  250. package/dist/internal/funding/TransferWebhook.d.ts.map +1 -0
  251. package/dist/internal/funding/TransferWebhook.js +43 -0
  252. package/dist/internal/funding/TransferWebhook.js.map +1 -0
  253. package/dist/internal/funding/index.d.ts +1 -0
  254. package/dist/internal/funding/index.d.ts.map +1 -1
  255. package/dist/internal/funding/index.js +1 -0
  256. package/dist/internal/funding/index.js.map +1 -1
  257. package/dist/internal/funding/providers/relay.d.ts.map +1 -1
  258. package/dist/internal/funding/providers/relay.js +3 -12
  259. package/dist/internal/funding/providers/relay.js.map +1 -1
  260. package/dist/internal/funding/providers/stargate.d.ts +127 -9
  261. package/dist/internal/funding/providers/stargate.d.ts.map +1 -1
  262. package/dist/internal/funding/providers/stargate.js +548 -112
  263. package/dist/internal/funding/providers/stargate.js.map +1 -1
  264. package/dist/internal/index.d.ts +1 -0
  265. package/dist/internal/index.d.ts.map +1 -1
  266. package/dist/internal/index.js +1 -0
  267. package/dist/internal/index.js.map +1 -1
  268. package/dist/internal/webhookDestinations/slack.d.ts.map +1 -1
  269. package/dist/internal/webhookDestinations/slack.js +16 -0
  270. package/dist/internal/webhookDestinations/slack.js.map +1 -1
  271. package/package.json +2 -2
  272. package/src/App.test.ts +100 -0
  273. package/src/App.ts +43 -3
  274. package/src/Client.test-d.ts +129 -2
  275. package/src/Scope.test.ts +20 -0
  276. package/src/Scope.ts +16 -0
  277. package/src/Webhooks.ts +2 -2
  278. package/src/admin/apps/api-keys.test.ts +75 -0
  279. package/src/admin/apps/api-keys.ts +64 -0
  280. package/src/admin/apps/earn-vaults.test.ts +1 -1
  281. package/src/admin/apps/earn-vaults.ts +2 -1
  282. package/src/admin/apps/organizations.test.ts +53 -1
  283. package/src/admin/apps/organizations.ts +90 -5
  284. package/src/admin/ui/src/lib/api-keys.ts +19 -0
  285. package/src/admin/ui/src/lib/organizations.test.ts +112 -1
  286. package/src/admin/ui/src/lib/organizations.ts +55 -0
  287. package/src/admin/ui/src/routes/api-keys.tsx +89 -2
  288. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +116 -0
  289. package/src/admin/ui.generated.ts +189 -151
  290. package/src/apps/Zones.test.ts +7 -7
  291. package/src/apps/Zones.ts +7 -7
  292. package/src/apps/composition.test.ts +2 -1
  293. package/src/apps/data/App.test.ts +41 -0
  294. package/src/apps/data/App.ts +30 -21
  295. package/src/apps/data/ZoneSelection.test.ts +2 -2
  296. package/src/apps/data/ZoneSelection.ts +8 -8
  297. package/src/apps/data/routes/activities.test.ts +1526 -12
  298. package/src/apps/data/routes/activities.ts +1774 -1356
  299. package/src/apps/data/routes/balances.ts +133 -97
  300. package/src/apps/data/routes/blocks.test.ts +533 -0
  301. package/src/apps/data/routes/blocks.ts +35 -16
  302. package/src/apps/data/routes/earn.test.ts +373 -16
  303. package/src/apps/data/routes/earn.ts +548 -79
  304. package/src/apps/data/routes/earn.zone-access.test.ts +6 -6
  305. package/src/apps/data/routes/exchanges.test.ts +740 -15
  306. package/src/apps/data/routes/exchanges.ts +954 -753
  307. package/src/apps/data/routes/fee-amm.ts +17 -18
  308. package/src/apps/data/routes/receipts.ts +47 -16
  309. package/src/apps/data/routes/tokens.test.ts +578 -0
  310. package/src/apps/data/routes/tokens.ts +283 -225
  311. package/src/apps/data/routes/transactions.ts +68 -29
  312. package/src/apps/data/routes/transfers.test.ts +421 -0
  313. package/src/apps/data/routes/transfers.ts +45 -27
  314. package/src/apps/data/routes/valuation.ts +94 -78
  315. package/src/apps/data/routes/webhooks.test.ts +21 -5
  316. package/src/apps/data/routes/webhooks.ts +63 -8
  317. package/src/apps/data/routes/zones.test.ts +2 -2
  318. package/src/apps/data/routes/zones.ts +1 -1
  319. package/src/apps/funding/App.ts +12 -2
  320. package/src/apps/funding/routes/deposit-addresses.test.ts +29 -7
  321. package/src/apps/funding/routes/deposit-addresses.ts +19 -14
  322. package/src/apps/funding/routes/quotes.test.ts +5 -9
  323. package/src/apps/funding/routes/transfers.test.ts +901 -23
  324. package/src/apps/funding/routes/transfers.ts +347 -64
  325. package/src/apps/management/Billing.ts +18 -5
  326. package/src/apps/management/routes/api-keys.test.ts +220 -0
  327. package/src/apps/management/routes/api-keys.ts +280 -3
  328. package/src/apps/management/routes/webhooks.test.ts +3 -3
  329. package/src/apps/management/routes/webhooks.ts +24 -25
  330. package/src/apps/relay/App.test.ts +212 -1
  331. package/src/apps/relay/App.ts +158 -29
  332. package/src/apps/relay/Sponsorships.ts +24 -1
  333. package/src/db/Db.ts +48 -1
  334. package/src/db/Schema.ts +22 -4
  335. package/src/db/tables/earnVaults.test.ts +9 -9
  336. package/src/db/tables/fundingCatalog.test.ts +16 -2
  337. package/src/db/tables/fundingCatalog.ts +9 -3
  338. package/src/db/tables/fundingTransferTransactions.test.ts +43 -0
  339. package/src/db/tables/fundingTransferTransactions.ts +79 -3
  340. package/src/db/tables/fundingTransfers.test.ts +26 -0
  341. package/src/db/tables/fundingTransfers.ts +36 -0
  342. package/src/db/tables/organizations.test.ts +41 -0
  343. package/src/db/tables/organizations.ts +49 -0
  344. package/src/db/tables/projects.test.ts +55 -0
  345. package/src/db/tables/projects.ts +46 -1
  346. package/src/db/tables/sponsoredTransactions.test.ts +338 -0
  347. package/src/db/tables/sponsoredTransactions.ts +197 -13
  348. package/src/db/tables/webhookSubscriptions.ts +18 -11
  349. package/src/handlers/internal/utils.test.ts +53 -0
  350. package/src/handlers/internal/utils.ts +15 -0
  351. package/src/internal/Auth.ts +12 -4
  352. package/src/internal/EarnVaults.capabilities.test.ts +2 -2
  353. package/src/internal/EarnVaults.test.ts +1 -1
  354. package/src/internal/EarnVaults.ts +5 -5
  355. package/src/internal/Fetch.test.ts +46 -0
  356. package/src/internal/Fetch.ts +56 -0
  357. package/src/internal/Log.test-d.ts +2 -0
  358. package/src/internal/Log.test.ts +21 -0
  359. package/src/internal/Log.ts +22 -5
  360. package/src/internal/OpenApi.ts +14 -4
  361. package/src/internal/Response.ts +1 -1
  362. package/src/internal/Schema.test.ts +2 -0
  363. package/src/internal/Schema.ts +12 -2
  364. package/src/internal/Store.test.ts +178 -0
  365. package/src/internal/Store.ts +104 -18
  366. package/src/internal/Tidx.test.ts +2 -1
  367. package/src/internal/Tidx.ts +7 -2
  368. package/src/internal/Timeout.test.ts +35 -0
  369. package/src/internal/Timeout.ts +73 -0
  370. package/src/internal/Timing.ts +16 -0
  371. package/src/internal/Viem.ts +39 -3
  372. package/src/internal/WebhookDestination.ts +3 -0
  373. package/src/internal/Webhooks.test.ts +45 -0
  374. package/src/internal/funding/Action.test.ts +41 -1
  375. package/src/internal/funding/Action.ts +69 -41
  376. package/src/internal/funding/Catalog.test.ts +34 -0
  377. package/src/internal/funding/Catalog.ts +28 -11
  378. package/src/internal/funding/DepositWebhook.ts +2 -1
  379. package/src/internal/funding/Evidence.ts +2 -13
  380. package/src/internal/funding/Provider.test.ts +73 -0
  381. package/src/internal/funding/Provider.ts +125 -28
  382. package/src/internal/funding/SourceObservation.ts +5 -9
  383. package/src/internal/funding/Transfer.test.ts +155 -0
  384. package/src/internal/funding/Transfer.ts +387 -147
  385. package/src/internal/funding/TransferReconciliation.test.ts +147 -0
  386. package/src/internal/funding/TransferReconciliation.ts +264 -0
  387. package/src/internal/funding/TransferWebhook.test.ts +128 -0
  388. package/src/internal/funding/TransferWebhook.ts +67 -0
  389. package/src/internal/funding/index.test.ts +1 -0
  390. package/src/internal/funding/index.ts +1 -0
  391. package/src/internal/funding/providers/index.test.ts +4 -167
  392. package/src/internal/funding/providers/relay.test.ts +2 -2
  393. package/src/internal/funding/providers/relay.ts +3 -15
  394. package/src/internal/funding/providers/stargate.test.ts +328 -0
  395. package/src/internal/funding/providers/stargate.ts +807 -135
  396. package/src/internal/index.test.ts +1 -0
  397. package/src/internal/index.ts +1 -0
  398. package/src/internal/webhookDestinations/slack.ts +15 -0
@@ -1,143 +1,579 @@
1
- import { Address } from 'ox';
1
+ import { AbiEvent, AbiFunction, Address, Hash, Hex } from 'ox';
2
+ import { BlockNotFoundError, parseEventLogs, publicActions, TransactionReceiptNotFoundError, } from 'viem';
2
3
  import * as z from 'zod/mini';
4
+ import * as Viem from '../../Viem.js';
5
+ import * as Action from '../Action.js';
6
+ import * as Chain from '../Chain.js';
3
7
  import * as FundingProvider from '../Provider.js';
4
- const defaultBaseUrl = 'https://transfer.layerzero-api.com/v1';
8
+ const approve = AbiFunction.from('function approve(address spender, uint256 amount)');
5
9
  const defaultFetch = (input, init) => globalThis.fetch(input, init);
6
- const sourceDetails = {
7
- STARGATE_V2_BUS: 'stargate:value-transfer-v1:bus',
8
- STARGATE_V2_TAXI: 'stargate:value-transfer-v1:taxi',
10
+ const destinationChainId = 'eip155:4217';
11
+ const destinationEid = 30_410;
12
+ const destinationPool = '0x8c76e2f6c5ceda9aa7772e7eff30280226c44392';
13
+ const destinationToken = '0x20C000000000000000000000b9537d11c60E8b50';
14
+ const layerZeroEndpoint = '0x1a44076050125825900e736c501f859c50fE728c';
15
+ const oftReceived = AbiEvent.from('event OFTReceived(bytes32 indexed guid, uint32 srcEid, address indexed toAddress, uint256 amountReceivedLD)');
16
+ const oftSent = AbiEvent.from('event OFTSent(bytes32 indexed guid, uint32 dstEid, address indexed fromAddress, uint256 amountSentLD, uint256 amountReceivedLD)');
17
+ const packetSent = AbiEvent.from('event PacketSent(bytes encodedPayload, bytes options, address sendLibrary)');
18
+ const quoteOft = AbiFunction.from('function quoteOFT((uint32 dstEid, bytes32 to, uint256 amountLD, uint256 minAmountLD, bytes extraOptions, bytes composeMsg, bytes oftCmd) sendParam) view returns ((uint256 minAmountLD, uint256 maxAmountLD) limit, (int256 feeAmountLD, string description)[] oftFeeDetails, (uint256 amountSentLD, uint256 amountReceivedLD) receipt)');
19
+ const quoteSend = AbiFunction.from('function quoteSend((uint32 dstEid, bytes32 to, uint256 amountLD, uint256 minAmountLD, bytes extraOptions, bytes composeMsg, bytes oftCmd) sendParam, bool payInLzToken) view returns ((uint256 nativeFee, uint256 lzTokenFee) fee)');
20
+ const sendToken = AbiFunction.from('function sendToken((uint32 dstEid, bytes32 to, uint256 amountLD, uint256 minAmountLD, bytes extraOptions, bytes composeMsg, bytes oftCmd) sendParam, (uint256 nativeFee, uint256 lzTokenFee) fee, address refundAddress) payable returns ((bytes32 guid, uint64 nonce, (uint256 nativeFee, uint256 lzTokenFee) fee) msgReceipt, (uint256 amountSentLD, uint256 amountReceivedLD) oftReceipt, (uint72 ticketId, bytes passengerBytes) ticket)');
21
+ const quoteTtlMs = 60_000;
22
+ const maximumLogBlockRange = 100000n;
23
+ const sourceEids = {
24
+ 'eip155:1': 30_101,
25
+ 'eip155:8453': 30_184,
9
26
  };
10
- var schema;
27
+ const transferEvent = AbiEvent.from('event Transfer(address indexed from, address indexed to, uint256 value)');
28
+ const zeroAddress = '0x0000000000000000000000000000000000000000';
29
+ /** Stargate provider schemas. */
30
+ export var schema;
11
31
  (function (schema) {
12
- const DecimalString = z.string().check(z.regex(/^\d+(\.\d+)?$/));
13
- const IntegerString = z.string().check(z.regex(/^\d+$/));
14
- const Quote = z.object({
15
- dstAmount: IntegerString,
16
- dstAmountMin: IntegerString,
17
- duration: z.optional(z.object({
18
- estimated: z.nullable(DecimalString),
19
- })),
20
- expiresAt: z.optional(z.iso.datetime()),
21
- id: z.string().check(z.minLength(1)),
22
- routeSteps: z
23
- .array(z.object({
24
- srcChainKey: z.string(),
25
- type: z.string(),
26
- }))
27
- .check(z.minLength(1)),
28
- srcAmount: IntegerString,
29
- });
30
- const Error = z.object({
31
- message: z.string(),
32
- status: z.union([z.string(), z.number()]),
33
- });
34
- schema.Quotes = z.object({
35
- error: z.optional(z.nullable(Error)),
36
- quotes: z.array(Quote),
37
- });
32
+ /** Configuration captured from one selected Stargate route. */
33
+ schema.Configuration = z
34
+ .strictObject({
35
+ destinationPoolAddress: z.optional(z
36
+ .string()
37
+ .check(z.regex(/^0x[0-9a-fA-F]{40}$/), z.describe('Stargate pool contract on the Tempo destination chain.'))),
38
+ poolAddress: z
39
+ .string()
40
+ .check(z.regex(/^0x[0-9a-fA-F]{40}$/), z.describe('Stargate pool contract on the source chain.')),
41
+ sourceEid: z.optional(z
42
+ .number()
43
+ .check(z.int(), z.positive(), z.describe('LayerZero endpoint ID for the source chain.'))),
44
+ })
45
+ .check(z.describe('Stargate configuration for one funding route.'));
38
46
  })(schema || (schema = {}));
39
- /** Creates a Stargate funding provider backed by LayerZero's `/quotes` endpoint. */
40
- export function stargate(options) {
41
- if (options.apiKey.trim().length === 0)
42
- throw new FundingProvider.ProviderConfigurationError();
43
- if (!Address.validate(options.userAddress, { strict: false }))
44
- throw new FundingProvider.ProviderConfigurationError();
45
- const endpoint = new URL(options.baseUrl ?? defaultBaseUrl);
46
- endpoint.pathname = `${endpoint.pathname.replace(/\/+$/, '')}/quotes`;
47
+ /** Creates a direct Stargate V2 OFT funding provider. */
48
+ export function stargate(options = {}) {
47
49
  const fetch = options.fetch ?? defaultFetch;
48
50
  const now = options.now ?? (() => new Date());
49
51
  return FundingProvider.from({
50
52
  id: 'stargate',
51
53
  name: 'Stargate',
52
54
  async getQuote({ candidate, route }, signal) {
53
- const response = await FundingProvider.requestJson(endpoint, {
54
- body: {
55
- amount: candidate.sourceAmount.amount,
56
- dstChainKey: route.destination.chain.slug,
57
- dstTokenAddress: candidate.destinationToken.address,
58
- dstWalletAddress: options.userAddress,
59
- options: { amountType: 'EXACT_SRC_AMOUNT' },
60
- srcChainKey: route.source.chain.slug,
61
- srcTokenAddress: candidate.sourceToken.address,
62
- srcWalletAddress: options.userAddress,
63
- },
55
+ const deployment = resolveDeployment({
56
+ configuration: candidate.configuration,
57
+ destinationChainId: route.destination.chain.id,
58
+ destinationTokenAddress: route.destination.address,
59
+ sourceChainId: route.source.chain.id,
60
+ sourceTokenAddress: route.source.address,
61
+ });
62
+ const sampledAt = now();
63
+ if (!deployment)
64
+ return unavailable({ message: 'ROUTE_NOT_CONFIGURED', now: sampledAt });
65
+ const sendParam = createSendParam({
66
+ amount: candidate.sourceAmount.amount,
67
+ recipient: zeroAddress,
68
+ });
69
+ const [limit, feeDetails, receipt] = await rpcClient({
64
70
  fetch,
65
- headers: { 'user-agent': 'tempo-api', 'x-api-key': options.apiKey },
66
- method: 'POST',
67
71
  signal,
72
+ urls: route.source.chain.rpcUrls,
73
+ }).readContract({
74
+ abi: [quoteOft],
75
+ address: deployment.pool,
76
+ args: [sendParam],
77
+ functionName: 'quoteOFT',
68
78
  });
69
- const parsed = schema.Quotes.safeParse(response);
70
- if (!parsed.success || parsed.data.error)
79
+ if (!isExactQuote({ amount: candidate.sourceAmount.amount, feeDetails, limit, receipt }))
80
+ return unavailable({ message: 'NO_EXACT_ROUTE', now: sampledAt });
81
+ return {
82
+ destinationAmountMin: receipt.amountReceivedLD.toString(),
83
+ destinationAmount: receipt.amountReceivedLD.toString(),
84
+ quality: quality(),
85
+ sampledAt: sampledAt.toISOString(),
86
+ status: 'available',
87
+ };
88
+ },
89
+ async prepareTransfer({ candidate, method, mode, recipient, sender }, signal) {
90
+ if (method !== 'transaction' ||
91
+ mode !== 'exactSource' ||
92
+ !Address.validate(recipient, { strict: false }) ||
93
+ !Address.validate(sender, { strict: false }))
94
+ throw new FundingProvider.ProviderConfigurationError();
95
+ const deployment = resolveDeployment({
96
+ configuration: candidate.configuration,
97
+ destinationChainId: candidate.destinationChain.id,
98
+ destinationTokenAddress: candidate.destinationToken.address,
99
+ sourceChainId: candidate.sourceChain.id,
100
+ sourceTokenAddress: candidate.sourceToken.address,
101
+ });
102
+ if (!deployment)
103
+ throw new FundingProvider.ProviderUnavailableError();
104
+ const sendParam = createSendParam({ amount: candidate.sourceAmount.amount, recipient });
105
+ const rpc = rpcClient({ fetch, signal, urls: candidate.route.source.chain.rpcUrls });
106
+ const [[limit, feeDetails, receipt], messagingFee, destinationBlock] = await Promise.all([
107
+ rpc.readContract({
108
+ abi: [quoteOft],
109
+ address: deployment.pool,
110
+ args: [sendParam],
111
+ functionName: 'quoteOFT',
112
+ }),
113
+ rpc.readContract({
114
+ abi: [quoteSend],
115
+ account: sender,
116
+ address: deployment.pool,
117
+ args: [sendParam, false],
118
+ functionName: 'quoteSend',
119
+ }),
120
+ rpcClient({
121
+ fetch,
122
+ signal,
123
+ urls: candidate.route.destination.chain.rpcUrls,
124
+ }).getBlock({ blockTag: 'finalized', includeTransactions: false }),
125
+ ]);
126
+ if (!isExactQuote({ amount: candidate.sourceAmount.amount, feeDetails, limit, receipt }))
127
+ throw new FundingProvider.ProviderUnavailableError();
128
+ if (messagingFee.lzTokenFee !== 0n)
71
129
  throw new FundingProvider.ProviderPayloadError();
130
+ const action = {
131
+ calls: [
132
+ {
133
+ data: AbiFunction.encodeData(approve, [
134
+ deployment.pool,
135
+ BigInt(candidate.sourceAmount.amount),
136
+ ]),
137
+ to: deployment.sourceToken,
138
+ value: '0x0',
139
+ },
140
+ {
141
+ data: AbiFunction.encodeData(sendToken, [sendParam, messagingFee, sender]),
142
+ to: deployment.pool,
143
+ value: Hex.fromNumber(messagingFee.nativeFee),
144
+ },
145
+ ],
146
+ type: 'evm:calls',
147
+ };
148
+ validateAction({
149
+ action,
150
+ configuration: candidate.configuration,
151
+ destinationTokenAddress: candidate.destinationToken.address,
152
+ recipient,
153
+ sender,
154
+ sourceAmount: candidate.sourceAmount.amount,
155
+ sourceChainId: candidate.sourceChain.id,
156
+ sourceTokenAddress: candidate.sourceToken.address,
157
+ });
72
158
  const sampledAt = now();
73
- const selected = selectQuote(parsed.data.quotes, {
74
- amount: candidate.sourceAmount.amount,
75
- now: sampledAt,
76
- sourceChainKey: route.source.chain.slug,
159
+ return {
160
+ action,
161
+ destinationAmountMin: receipt.amountReceivedLD.toString(),
162
+ destinationAmount: receipt.amountReceivedLD.toString(),
163
+ expiresAt: new Date(sampledAt.getTime() + quoteTtlMs).toISOString(),
164
+ fees: messagingFee.nativeFee === 0n
165
+ ? []
166
+ : [
167
+ {
168
+ amount: messagingFee.nativeFee.toString(),
169
+ side: 'source',
170
+ token: nativeToken(candidate.sourceChain.id),
171
+ },
172
+ ],
173
+ providerState: {
174
+ destinationBlockNumber: destinationBlock.number.toString(),
175
+ routeConfiguration: candidate.configuration,
176
+ },
177
+ quality: quality(),
178
+ sampledAt: sampledAt.toISOString(),
179
+ };
180
+ },
181
+ validateTransferAction({ action, candidate, recipient, sender }) {
182
+ return {
183
+ nativeValues: validateAction({
184
+ action,
185
+ configuration: candidate.configuration,
186
+ destinationTokenAddress: candidate.destinationToken.address,
187
+ recipient,
188
+ sender,
189
+ sourceAmount: candidate.sourceAmount.amount,
190
+ sourceChainId: candidate.sourceChain.id,
191
+ sourceTokenAddress: candidate.sourceToken.address,
192
+ }),
193
+ };
194
+ },
195
+ async verifySourceTransaction({ destinationChain, providerState, routeConfiguration, sourceChain, transactionHash, transfer, }, signal) {
196
+ if (transfer.method !== 'transaction' || transfer.mode !== 'exactSource' || !transfer.sender)
197
+ return { type: 'invalid' };
198
+ const configuration = providerState?.['routeConfiguration'] ?? routeConfiguration;
199
+ const evidence = await verifySourceTransaction({
200
+ configuration,
201
+ destinationTokenAddress: transfer.destinationToken.address,
202
+ fetch,
203
+ recipient: transfer.recipient,
204
+ sender: transfer.sender,
205
+ signal,
206
+ sourceAmount: transfer.sourceAmount.baseUnits,
207
+ sourceChain,
208
+ sourceTokenAddress: transfer.sourceToken.address,
209
+ transactionHash,
210
+ validAfter: transfer.quote.sampledAt,
77
211
  });
78
- if (!selected)
79
- return FundingProvider.unavailableResult({
80
- detail: 'stargate:value-transfer-v1',
81
- message: 'NO_STARGATE_ROUTE',
82
- now: sampledAt,
83
- source: 'providerQuote',
212
+ if (evidence.type === 'invalid')
213
+ return evidence;
214
+ if (evidence.type !== 'verified')
215
+ return { type: 'pending' };
216
+ const destinationBlockNumber = typeof providerState?.['destinationBlockNumber'] === 'string' &&
217
+ /^\d+$/.test(providerState['destinationBlockNumber'])
218
+ ? providerState['destinationBlockNumber']
219
+ : await blockNumberBefore({
220
+ chain: destinationChain,
221
+ fetch,
222
+ signal,
223
+ timestamp: transfer.quote.sampledAt,
84
224
  });
85
- const estimated = estimatedSeconds(selected.quote.duration?.estimated);
86
225
  return {
87
- ...(selected.quote.expiresAt ? { expiresAt: selected.quote.expiresAt } : {}),
88
- destinationAmountMin: selected.quote.dstAmountMin,
89
- destinationAmount: selected.quote.dstAmount,
90
- quality: {
91
- ...(estimated === undefined ? {} : { estimatedSeconds: estimated }),
92
- liquiditySource: 'providerQuote',
93
- sourceDetail: sourceDetails[selected.type],
94
- tier: 'liquid',
226
+ providerState: {
227
+ ...providerState,
228
+ destinationBlockNumber,
229
+ routeConfiguration: configuration,
230
+ stargate: {
231
+ guid: evidence.guid,
232
+ sourceBlock: {
233
+ hash: evidence.sourceBlock.hash,
234
+ number: evidence.sourceBlock.number.toString(),
235
+ },
236
+ sourceEid: evidence.sourceEid,
237
+ },
95
238
  },
96
- sampledAt: sampledAt.toISOString(),
97
- status: 'available',
239
+ type: 'verified',
98
240
  };
99
241
  },
100
242
  });
101
243
  }
102
- function selectQuote(quotes, options) {
103
- return quotes
104
- .flatMap((quote) => {
105
- const type = quote.routeSteps
106
- .filter((step) => step.srcChainKey === options.sourceChainKey)
107
- .map((step) => step.type)
108
- .find(isStargateType);
109
- if (!type)
110
- return [];
111
- if (quote.expiresAt !== undefined &&
112
- new Date(quote.expiresAt).getTime() <= options.now.getTime())
113
- return [];
114
- if (quote.srcAmount !== options.amount ||
115
- BigInt(quote.dstAmount) <= 0n ||
116
- BigInt(quote.dstAmountMin) <= 0n ||
117
- BigInt(quote.dstAmountMin) > BigInt(quote.dstAmount))
244
+ /** Validates one direct Stargate action and returns its exact native-value allowance. */
245
+ export function validateAction(options) {
246
+ try {
247
+ const action = Action.schema.EvmCalls.parse(options.action);
248
+ const deployment = resolveDeployment({
249
+ configuration: options.configuration,
250
+ destinationChainId,
251
+ destinationTokenAddress: options.destinationTokenAddress,
252
+ sourceChainId: options.sourceChainId,
253
+ sourceTokenAddress: options.sourceTokenAddress,
254
+ });
255
+ if (!deployment || action.calls.length !== 2)
118
256
  throw new FundingProvider.ProviderPayloadError();
119
- return [{ quote, type }];
120
- })
121
- .sort((a, b) => {
122
- const delta = BigInt(b.quote.dstAmountMin) - BigInt(a.quote.dstAmountMin);
123
- if (delta > 0n)
124
- return 1;
125
- if (delta < 0n)
126
- return -1;
127
- return 0;
128
- })[0];
257
+ const [approval, execution] = action.calls;
258
+ if (!Address.isEqual(approval.to, deployment.sourceToken) ||
259
+ BigInt(approval.value) !== 0n)
260
+ throw new FundingProvider.ProviderPayloadError();
261
+ const [spender, approvalAmount] = AbiFunction.decodeData(approve, approval.data);
262
+ if (!Address.isEqual(spender, deployment.pool) ||
263
+ approvalAmount !== BigInt(options.sourceAmount))
264
+ throw new FundingProvider.ProviderPayloadError();
265
+ validateSend({
266
+ data: execution.data,
267
+ nativeValue: BigInt(execution.value),
268
+ pool: deployment.pool,
269
+ recipient: options.recipient,
270
+ sender: options.sender,
271
+ sourceAmount: options.sourceAmount,
272
+ to: execution.to,
273
+ });
274
+ return [{ to: execution.to, value: execution.value }];
275
+ }
276
+ catch (cause) {
277
+ if (cause instanceof FundingProvider.ProviderPayloadError)
278
+ throw cause;
279
+ throw new FundingProvider.ProviderPayloadError();
280
+ }
281
+ }
282
+ /** Verifies a submitted Stargate source transaction against stored transfer terms. */
283
+ export async function verifySourceTransaction(options) {
284
+ const deployment = resolveDeployment({
285
+ configuration: options.configuration,
286
+ destinationChainId,
287
+ destinationTokenAddress: options.destinationTokenAddress,
288
+ sourceChainId: options.sourceChain.id,
289
+ sourceTokenAddress: options.sourceTokenAddress,
290
+ });
291
+ if (!deployment ||
292
+ options.sourceChain.kind !== 'evm' ||
293
+ !Hash.validate(options.transactionHash) ||
294
+ !Address.validate(options.recipient, { strict: false }) ||
295
+ !Address.validate(options.sender, { strict: false }))
296
+ return { type: 'invalid' };
297
+ const rpc = rpcClient({
298
+ fetch: options.fetch ?? defaultFetch,
299
+ signal: options.signal,
300
+ urls: options.sourceChain.rpcUrls,
301
+ });
302
+ const hash = options.transactionHash;
303
+ const [chainId, receipt] = await Promise.all([
304
+ rpc.getChainId(),
305
+ rpc.getTransactionReceipt({ hash }).catch((cause) => {
306
+ if (cause instanceof TransactionReceiptNotFoundError)
307
+ return undefined;
308
+ throw cause;
309
+ }),
310
+ ]);
311
+ if (chainId !== Number(Chain.eip155Id(options.sourceChain)))
312
+ return { type: 'invalid' };
313
+ const block = !receipt || receipt.blockNumber === null
314
+ ? undefined
315
+ : await rpc
316
+ .getBlock({ blockNumber: receipt.blockNumber, includeTransactions: false })
317
+ .catch((cause) => {
318
+ if (cause instanceof BlockNotFoundError)
319
+ return undefined;
320
+ throw cause;
321
+ });
322
+ if (!receipt ||
323
+ receipt.blockNumber === null ||
324
+ !block ||
325
+ !Hex.isEqual(block.hash, receipt.blockHash)) {
326
+ if (!options.sourceBlock)
327
+ return { type: 'pending' };
328
+ const finalized = await rpc.getBlock({ blockTag: 'finalized', includeTransactions: false });
329
+ if (finalized.number < options.sourceBlock.number)
330
+ return { type: 'pending' };
331
+ const canonical = await rpc
332
+ .getBlock({ blockNumber: options.sourceBlock.number, includeTransactions: false })
333
+ .catch((cause) => {
334
+ if (cause instanceof BlockNotFoundError)
335
+ return undefined;
336
+ throw cause;
337
+ });
338
+ if (!canonical || Hex.isEqual(canonical.hash, options.sourceBlock.hash))
339
+ return { type: 'pending' };
340
+ return { type: 'reorged' };
341
+ }
342
+ if (receipt.status !== 'success')
343
+ return { type: 'invalid' };
344
+ const validAfter = Math.floor(Date.parse(options.validAfter) / 1_000);
345
+ if (!Number.isSafeInteger(validAfter) || block.timestamp < BigInt(validAfter))
346
+ return { type: 'invalid' };
347
+ const amount = BigInt(options.sourceAmount);
348
+ const sourceEvents = parseEventLogs({ abi: [oftSent], logs: receipt.logs, strict: true }).filter(({ address, args }) => Address.isEqual(address, deployment.pool) &&
349
+ args.dstEid === destinationEid &&
350
+ Address.isEqual(args.fromAddress, options.sender) &&
351
+ args.amountSentLD === amount &&
352
+ args.amountReceivedLD === amount);
353
+ const transfers = parseEventLogs({
354
+ abi: [transferEvent],
355
+ logs: receipt.logs,
356
+ strict: true,
357
+ }).filter(({ address, args }) => Address.isEqual(address, deployment.sourceToken) &&
358
+ Address.isEqual(args.from, options.sender) &&
359
+ Address.isEqual(args.to, deployment.pool) &&
360
+ args.value === amount);
361
+ if (sourceEvents.length !== 1 || transfers.length !== 1)
362
+ return { type: 'invalid' };
363
+ const guid = sourceEvents[0].args.guid;
364
+ // PacketV1's 113-byte header is followed by Stargate's type, asset id, recipient, and amount.
365
+ const packets = parseEventLogs({ abi: [packetSent], logs: receipt.logs, strict: true }).filter(({ address, args }) => {
366
+ const packet = args.encodedPayload;
367
+ return (Address.isEqual(address, layerZeroEndpoint) &&
368
+ Hex.size(packet) === 156 &&
369
+ Hex.toNumber(Hex.slice(packet, 0, 1)) === 1 &&
370
+ Hex.toNumber(Hex.slice(packet, 9, 13)) === deployment.sourceEid &&
371
+ Hex.toNumber(Hex.slice(packet, 45, 49)) === destinationEid &&
372
+ Hex.isEqual(Hex.slice(packet, 81, 113), guid) &&
373
+ Hex.toNumber(Hex.slice(packet, 113, 114)) === 1 &&
374
+ Hex.isEqual(Hex.slice(packet, 116, 148), recipientBytes32(options.recipient)) &&
375
+ Hex.toBigInt(Hex.slice(packet, 148, 156)) === amount);
376
+ });
377
+ if (packets.length !== 1)
378
+ return { type: 'invalid' };
379
+ return {
380
+ guid,
381
+ sourceBlock: { hash: block.hash, number: block.number },
382
+ sourceEid: deployment.sourceEid,
383
+ type: 'verified',
384
+ };
385
+ }
386
+ /** Finds and verifies the finalized Stargate delivery directly on Tempo. */
387
+ export async function verifyDestinationDelivery(options) {
388
+ const deployment = resolveDeployment({
389
+ configuration: options.configuration,
390
+ destinationChainId: options.destinationChain.id,
391
+ destinationTokenAddress: options.destinationTokenAddress,
392
+ sourceChainId: options.sourceChainId,
393
+ sourceTokenAddress: options.sourceTokenAddress,
394
+ });
395
+ if (!deployment ||
396
+ options.destinationChain.kind !== 'evm' ||
397
+ !/^\d+$/.test(options.destinationBlockNumber) ||
398
+ !Hash.validate(options.guid) ||
399
+ !Address.validate(options.recipient, { strict: false }))
400
+ return { type: 'invalid' };
401
+ const rpc = rpcClient({
402
+ fetch: options.fetch ?? defaultFetch,
403
+ urls: options.destinationChain.rpcUrls,
404
+ });
405
+ const [chainId, finalized] = await Promise.all([
406
+ rpc.getChainId(),
407
+ rpc.getBlock({ blockTag: 'finalized', includeTransactions: false }),
408
+ ]);
409
+ if (chainId !== Number(Chain.eip155Id(options.destinationChain)))
410
+ return { type: 'invalid' };
411
+ const amount = BigInt(options.destinationAmount);
412
+ const discovered = await (async () => {
413
+ for (let fromBlock = BigInt(options.destinationBlockNumber); fromBlock <= finalized.number; fromBlock += maximumLogBlockRange) {
414
+ const toBlock = fromBlock + maximumLogBlockRange - 1n;
415
+ const logs = await rpc.getLogs({
416
+ address: deployment.destinationPool,
417
+ args: { guid: options.guid, toAddress: options.recipient },
418
+ event: oftReceived,
419
+ fromBlock,
420
+ strict: true,
421
+ toBlock: toBlock > finalized.number ? finalized.number : toBlock,
422
+ });
423
+ const matches = logs.filter(({ args, transactionHash }) => transactionHash &&
424
+ args.srcEid === deployment.sourceEid &&
425
+ args.amountReceivedLD === amount);
426
+ if (logs.length !== matches.length || matches.length > 1)
427
+ return { type: 'invalid' };
428
+ if (matches[0]?.transactionHash)
429
+ return { transactionHash: matches[0].transactionHash, type: 'found' };
430
+ }
431
+ return { type: 'pending' };
432
+ })();
433
+ if (discovered.type !== 'found')
434
+ return discovered;
435
+ const { transactionHash } = discovered;
436
+ const receipt = await rpc.getTransactionReceipt({ hash: transactionHash }).catch((cause) => {
437
+ if (cause instanceof TransactionReceiptNotFoundError)
438
+ return undefined;
439
+ throw cause;
440
+ });
441
+ if (!receipt || receipt.blockNumber === null)
442
+ return { type: 'pending' };
443
+ if (receipt.status !== 'success' || receipt.blockNumber > finalized.number)
444
+ return { type: 'invalid' };
445
+ const transfers = parseEventLogs({
446
+ abi: [transferEvent],
447
+ logs: receipt.logs,
448
+ strict: true,
449
+ }).filter(({ address, args }) => Address.isEqual(address, destinationToken) &&
450
+ Address.isEqual(args.from, zeroAddress) &&
451
+ Address.isEqual(args.to, options.recipient) &&
452
+ args.value === amount);
453
+ if (transfers.length !== 1)
454
+ return { type: 'invalid' };
455
+ return { transactionHash, type: 'verified' };
129
456
  }
130
- function isStargateType(type) {
131
- return Object.hasOwn(sourceDetails, type);
457
+ function rpcClient(options) {
458
+ if (options.urls.length === 0)
459
+ throw new FundingProvider.ProviderConfigurationError();
460
+ return Viem.createEvmClient(options).extend(publicActions);
132
461
  }
133
- function estimatedSeconds(milliseconds) {
134
- if (milliseconds === undefined || milliseconds === null)
135
- return undefined;
136
- const [whole = '0', fraction] = milliseconds.split('.');
137
- const roundedMilliseconds = BigInt(whole) + (fraction !== undefined && /[1-9]/.test(fraction) ? 1n : 0n);
138
- const seconds = (roundedMilliseconds + 999n) / 1000n;
139
- if (seconds > BigInt(Number.MAX_SAFE_INTEGER))
462
+ async function blockNumberBefore(options) {
463
+ if (options.chain.kind !== 'evm')
464
+ throw new FundingProvider.ProviderConfigurationError();
465
+ const timestamp = Date.parse(options.timestamp);
466
+ if (!Number.isFinite(timestamp))
140
467
  throw new FundingProvider.ProviderPayloadError();
141
- return Number(seconds);
468
+ const rpc = rpcClient({
469
+ fetch: options.fetch,
470
+ signal: options.signal,
471
+ urls: options.chain.rpcUrls,
472
+ });
473
+ const [chainId, finalized] = await Promise.all([
474
+ rpc.getChainId(),
475
+ rpc.getBlock({ blockTag: 'finalized', includeTransactions: false }),
476
+ ]);
477
+ if (chainId !== Number(Chain.eip155Id(options.chain)))
478
+ throw new FundingProvider.ProviderConfigurationError();
479
+ const target = BigInt(Math.floor(timestamp / 1_000) - 1);
480
+ let lower = 0n;
481
+ let upper = finalized.number;
482
+ while (lower < upper) {
483
+ const middle = (lower + upper + 1n) / 2n;
484
+ const block = await rpc.getBlock({ blockNumber: middle, includeTransactions: false });
485
+ if (block.timestamp <= target)
486
+ lower = middle;
487
+ else
488
+ upper = middle - 1n;
489
+ }
490
+ return lower.toString();
491
+ }
492
+ function createSendParam(options) {
493
+ const amount = BigInt(options.amount);
494
+ return {
495
+ amountLD: amount,
496
+ composeMsg: '0x',
497
+ dstEid: destinationEid,
498
+ extraOptions: '0x',
499
+ minAmountLD: amount,
500
+ oftCmd: '0x',
501
+ to: recipientBytes32(options.recipient),
502
+ };
503
+ }
504
+ function isExactQuote(options) {
505
+ const amount = BigInt(options.amount);
506
+ return (amount >= options.limit.minAmountLD &&
507
+ amount <= options.limit.maxAmountLD &&
508
+ options.feeDetails.every((fee) => fee.feeAmountLD >= 0n) &&
509
+ options.receipt.amountSentLD === amount &&
510
+ options.receipt.amountReceivedLD === amount);
511
+ }
512
+ function nativeToken(sourceChainId) {
513
+ return {
514
+ address: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
515
+ currency: 'ETH',
516
+ decimals: 18,
517
+ name: 'Ether',
518
+ standard: 'native',
519
+ symbol: 'ETH',
520
+ tokenKey: `${sourceChainId}/slip44:60`,
521
+ verified: true,
522
+ };
523
+ }
524
+ function quality() {
525
+ return {
526
+ liquiditySource: 'onchain',
527
+ sourceDetail: 'stargate:oft-v2:taxi',
528
+ tier: 'liquid',
529
+ };
530
+ }
531
+ function recipientBytes32(recipient) {
532
+ if (!Address.validate(recipient, { strict: false }))
533
+ throw new FundingProvider.ProviderConfigurationError();
534
+ return Hex.padLeft(recipient, 32);
535
+ }
536
+ function validateSend(options) {
537
+ const [sendParam, messagingFee, refundAddress] = AbiFunction.decodeData(sendToken, options.data);
538
+ const amount = BigInt(options.sourceAmount);
539
+ if (!Address.isEqual(options.to, options.pool) ||
540
+ sendParam.amountLD !== amount ||
541
+ sendParam.composeMsg !== '0x' ||
542
+ sendParam.dstEid !== destinationEid ||
543
+ sendParam.extraOptions !== '0x' ||
544
+ sendParam.minAmountLD !== amount ||
545
+ sendParam.oftCmd !== '0x' ||
546
+ !Hex.isEqual(sendParam.to, recipientBytes32(options.recipient)) ||
547
+ messagingFee.lzTokenFee !== 0n ||
548
+ messagingFee.nativeFee !== options.nativeValue ||
549
+ !Address.isEqual(refundAddress, options.sender))
550
+ throw new FundingProvider.ProviderPayloadError();
551
+ }
552
+ function resolveDeployment(options) {
553
+ const parsed = schema.Configuration.safeParse(options.configuration);
554
+ const sourceEid = parsed.success &&
555
+ (parsed.data.sourceEid ?? sourceEids[options.sourceChainId]);
556
+ if (!parsed.success ||
557
+ !sourceEid ||
558
+ options.destinationChainId !== destinationChainId ||
559
+ !options.sourceChainId.startsWith('eip155:') ||
560
+ !Address.validate(options.destinationTokenAddress, { strict: false }) ||
561
+ !Address.validate(options.sourceTokenAddress, { strict: false }) ||
562
+ !Address.isEqual(options.destinationTokenAddress, destinationToken))
563
+ return undefined;
564
+ return {
565
+ destinationPool: Address.checksum(parsed.data.destinationPoolAddress ?? destinationPool),
566
+ pool: Address.checksum(parsed.data.poolAddress),
567
+ sourceEid,
568
+ sourceToken: Address.checksum(options.sourceTokenAddress),
569
+ };
570
+ }
571
+ function unavailable(options) {
572
+ return FundingProvider.unavailableResult({
573
+ detail: 'stargate:oft-v2',
574
+ message: options.message,
575
+ now: options.now,
576
+ source: 'onchain',
577
+ });
142
578
  }
143
579
  //# sourceMappingURL=stargate.js.map