@opendatalabs/vana-sdk 0.1.0-alpha.7ee7635 → 0.1.0-alpha.8117ac2

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 (700) hide show
  1. package/dist/__tests__/waitForTransactionEvents.test.d.ts +1 -0
  2. package/dist/browser.cjs.map +1 -1
  3. package/dist/browser.d.ts +36 -2
  4. package/dist/browser.js.map +1 -1
  5. package/dist/chains/definitions.cjs +9 -6
  6. package/dist/chains/definitions.cjs.map +1 -1
  7. package/dist/chains/definitions.d.ts +9 -11
  8. package/dist/chains/definitions.js +9 -6
  9. package/dist/chains/definitions.js.map +1 -1
  10. package/dist/chains/index.cjs.map +1 -1
  11. package/dist/chains/index.d.ts +34 -2
  12. package/dist/chains/index.js.map +1 -1
  13. package/dist/chains.browser.d.ts +8 -2
  14. package/dist/chains.d.ts +8 -2
  15. package/dist/chains.node.d.ts +8 -2
  16. package/dist/config/addresses.d.ts +8 -45
  17. package/dist/config/chains.cjs.map +1 -1
  18. package/dist/config/chains.d.ts +108 -13
  19. package/dist/config/chains.js.map +1 -1
  20. package/dist/config/default-services.cjs +60 -0
  21. package/dist/config/default-services.cjs.map +1 -0
  22. package/dist/config/default-services.d.ts +46 -0
  23. package/dist/config/default-services.js +33 -0
  24. package/dist/config/default-services.js.map +1 -0
  25. package/dist/config/default-services.test.d.ts +1 -0
  26. package/dist/config/features.d.ts +1 -3
  27. package/dist/config/tests/addresses.test.d.ts +1 -0
  28. package/dist/contracts/contractController.cjs +3 -3
  29. package/dist/contracts/contractController.cjs.map +1 -1
  30. package/dist/contracts/contractController.d.ts +77 -59
  31. package/dist/contracts/contractController.js +4 -7
  32. package/dist/contracts/contractController.js.map +1 -1
  33. package/dist/contracts/tests/contractController.test.d.ts +1 -0
  34. package/dist/controllers/__tests__/data-consistency-integration.test.d.ts +7 -0
  35. package/dist/controllers/__tests__/schemas-edge-cases.test.d.ts +1 -0
  36. package/dist/controllers/base.cjs +116 -0
  37. package/dist/controllers/base.cjs.map +1 -0
  38. package/dist/controllers/base.d.ts +94 -0
  39. package/dist/controllers/base.js +92 -0
  40. package/dist/controllers/base.js.map +1 -0
  41. package/dist/controllers/data-error-handling.test.d.ts +1 -0
  42. package/dist/controllers/data.cjs +699 -373
  43. package/dist/controllers/data.cjs.map +1 -1
  44. package/dist/controllers/data.d.ts +368 -228
  45. package/dist/controllers/data.js +712 -376
  46. package/dist/controllers/data.js.map +1 -1
  47. package/dist/controllers/permissions.cjs +688 -489
  48. package/dist/controllers/permissions.cjs.map +1 -1
  49. package/dist/controllers/permissions.d.ts +98 -165
  50. package/dist/controllers/permissions.js +688 -489
  51. package/dist/controllers/permissions.js.map +1 -1
  52. package/dist/controllers/protocol.cjs +15 -11
  53. package/dist/controllers/protocol.cjs.map +1 -1
  54. package/dist/controllers/protocol.d.ts +34 -84
  55. package/dist/controllers/protocol.js +15 -14
  56. package/dist/controllers/protocol.js.map +1 -1
  57. package/dist/controllers/schemas.cjs +57 -52
  58. package/dist/controllers/schemas.cjs.map +1 -1
  59. package/dist/controllers/schemas.d.ts +55 -61
  60. package/dist/controllers/schemas.js +57 -52
  61. package/dist/controllers/schemas.js.map +1 -1
  62. package/dist/controllers/server-additional.test.d.ts +1 -0
  63. package/dist/controllers/server.cjs +32 -25
  64. package/dist/controllers/server.cjs.map +1 -1
  65. package/dist/controllers/server.d.ts +53 -58
  66. package/dist/controllers/server.js +32 -25
  67. package/dist/controllers/server.js.map +1 -1
  68. package/dist/core/apiClient.cjs +68 -15
  69. package/dist/core/apiClient.cjs.map +1 -1
  70. package/dist/core/apiClient.d.ts +137 -16
  71. package/dist/core/apiClient.js +72 -22
  72. package/dist/core/apiClient.js.map +1 -1
  73. package/dist/core/client.cjs +7 -7
  74. package/dist/core/client.cjs.map +1 -1
  75. package/dist/core/client.d.ts +6 -9
  76. package/dist/core/client.js +7 -7
  77. package/dist/core/client.js.map +1 -1
  78. package/dist/core/core.test.d.ts +1 -0
  79. package/dist/core/generics.cjs +41 -12
  80. package/dist/core/generics.cjs.map +1 -1
  81. package/dist/core/generics.d.ts +104 -19
  82. package/dist/core/generics.js +52 -32
  83. package/dist/core/generics.js.map +1 -1
  84. package/dist/core/tests/apiClient.test.d.ts +1 -0
  85. package/dist/core/tests/client.test.d.ts +1 -0
  86. package/dist/core/tests/generics.test.d.ts +1 -0
  87. package/dist/core.cjs +115 -47
  88. package/dist/core.cjs.map +1 -1
  89. package/dist/core.d.ts +24 -74
  90. package/dist/core.js +137 -72
  91. package/dist/core.js.map +1 -1
  92. package/dist/crypto/ecies/__tests__/base.test.d.ts +4 -0
  93. package/dist/crypto/ecies/__tests__/compatibility.test.d.ts +8 -0
  94. package/dist/crypto/ecies/__tests__/constants.test.d.ts +4 -0
  95. package/dist/crypto/ecies/__tests__/native-parity.test.d.ts +7 -0
  96. package/dist/crypto/ecies/__tests__/normalization.test.d.ts +1 -0
  97. package/dist/crypto/ecies/__tests__/test-vectors.d.ts +2 -4
  98. package/dist/crypto/ecies/base.cjs +4 -3
  99. package/dist/crypto/ecies/base.cjs.map +1 -1
  100. package/dist/crypto/ecies/base.d.ts +2 -5
  101. package/dist/crypto/ecies/base.js +12 -15
  102. package/dist/crypto/ecies/base.js.map +1 -1
  103. package/dist/crypto/ecies/browser.cjs +2 -1
  104. package/dist/crypto/ecies/browser.cjs.map +1 -1
  105. package/dist/crypto/ecies/browser.d.ts +2 -7
  106. package/dist/crypto/ecies/browser.js +2 -1
  107. package/dist/crypto/ecies/browser.js.map +1 -1
  108. package/dist/crypto/ecies/constants.d.ts +7 -9
  109. package/dist/crypto/ecies/index.d.ts +8 -1
  110. package/dist/crypto/ecies/interface.cjs +4 -5
  111. package/dist/crypto/ecies/interface.cjs.map +1 -1
  112. package/dist/crypto/ecies/interface.d.ts +9 -11
  113. package/dist/crypto/ecies/interface.js +4 -5
  114. package/dist/crypto/ecies/interface.js.map +1 -1
  115. package/dist/crypto/ecies/node.cjs +3 -2
  116. package/dist/crypto/ecies/node.cjs.map +1 -1
  117. package/dist/crypto/ecies/node.d.ts +2 -7
  118. package/dist/crypto/ecies/node.js +11 -16
  119. package/dist/crypto/ecies/node.js.map +1 -1
  120. package/dist/crypto/ecies/utils.cjs +2 -41
  121. package/dist/crypto/ecies/utils.cjs.map +1 -1
  122. package/dist/crypto/ecies/utils.d.ts +3 -40
  123. package/dist/crypto/ecies/utils.js +1 -35
  124. package/dist/crypto/ecies/utils.js.map +1 -1
  125. package/dist/crypto/services/WalletKeyEncryptionService.cjs +2 -2
  126. package/dist/crypto/services/WalletKeyEncryptionService.cjs.map +1 -1
  127. package/dist/crypto/services/WalletKeyEncryptionService.d.ts +3 -7
  128. package/dist/crypto/services/WalletKeyEncryptionService.js +5 -9
  129. package/dist/crypto/services/WalletKeyEncryptionService.js.map +1 -1
  130. package/dist/crypto/services/WalletKeyEncryptionService.test.d.ts +1 -0
  131. package/dist/diagnostics.d.ts +1 -3
  132. package/dist/diagnostics.test.d.ts +1 -0
  133. package/dist/errors.cjs +16 -0
  134. package/dist/errors.cjs.map +1 -1
  135. package/dist/errors.d.ts +53 -15
  136. package/dist/errors.js +18 -6
  137. package/dist/errors.js.map +1 -1
  138. package/dist/generated/abi/ComputeEngineImplementation.d.ts +2 -3
  139. package/dist/generated/abi/ComputeInstructionRegistryImplementation.cjs.map +1 -1
  140. package/dist/generated/abi/ComputeInstructionRegistryImplementation.d.ts +2 -3
  141. package/dist/generated/abi/ComputeInstructionRegistryImplementation.js.map +1 -1
  142. package/dist/generated/abi/DATFactoryImplementation.d.ts +2 -3
  143. package/dist/generated/abi/DATImplementation.d.ts +2 -3
  144. package/dist/generated/abi/DATPausableImplementation.d.ts +2 -3
  145. package/dist/generated/abi/DATVotesImplementation.d.ts +2 -3
  146. package/dist/generated/abi/DLPPerformanceImplementation.d.ts +2 -3
  147. package/dist/generated/abi/DLPRegistryImplementation.d.ts +2 -3
  148. package/dist/generated/abi/DLPRegistryTreasuryImplementation.d.ts +2 -3
  149. package/dist/generated/abi/DLPRewardDeployerImplementation.d.ts +2 -3
  150. package/dist/generated/abi/DLPRewardDeployerTreasuryImplementation.d.ts +2 -3
  151. package/dist/generated/abi/DLPRewardSwapImplementation.d.ts +2 -3
  152. package/dist/generated/abi/DLPRootImplementation.d.ts +1 -3
  153. package/dist/generated/abi/DLPTreasuryImplementation.d.ts +2 -3
  154. package/dist/generated/abi/DataLiquidityPoolImplementation.d.ts +1 -3
  155. package/dist/generated/abi/DataPortabilityGranteesImplementation.d.ts +2 -3
  156. package/dist/generated/abi/DataPortabilityPermissionsImplementation.cjs.map +1 -1
  157. package/dist/generated/abi/DataPortabilityPermissionsImplementation.d.ts +2 -3
  158. package/dist/generated/abi/DataPortabilityPermissionsImplementation.js.map +1 -1
  159. package/dist/generated/abi/DataPortabilityServersImplementation.cjs.map +1 -1
  160. package/dist/generated/abi/DataPortabilityServersImplementation.d.ts +2 -3
  161. package/dist/generated/abi/DataPortabilityServersImplementation.js.map +1 -1
  162. package/dist/generated/abi/DataRefinerRegistryImplementation.d.ts +2 -3
  163. package/dist/generated/abi/DataRegistryImplementation.d.ts +2 -3
  164. package/dist/generated/abi/QueryEngineImplementation.d.ts +2 -3
  165. package/dist/generated/abi/SwapHelperImplementation.d.ts +2 -3
  166. package/dist/generated/abi/TeePoolDedicatedGpuImplementation.d.ts +2 -3
  167. package/dist/generated/abi/TeePoolDedicatedStandardImplementation.d.ts +2 -3
  168. package/dist/generated/abi/TeePoolEphemeralStandardImplementation.d.ts +2 -3
  169. package/dist/generated/abi/TeePoolImplementation.d.ts +2 -3
  170. package/dist/generated/abi/TeePoolPersistentGpuImplementation.d.ts +2 -3
  171. package/dist/generated/abi/TeePoolPersistentStandardImplementation.d.ts +2 -3
  172. package/dist/generated/abi/TeePoolPhalaImplementation.d.ts +2 -3
  173. package/dist/generated/abi/VanaEpochImplementation.d.ts +2 -3
  174. package/dist/generated/abi/VanaPoolEntityImplementation.d.ts +2 -3
  175. package/dist/generated/abi/VanaPoolStakingImplementation.d.ts +2 -3
  176. package/dist/generated/abi/VanaPoolTreasuryImplementation.d.ts +2 -3
  177. package/dist/generated/abi/index.d.ts +37 -39
  178. package/dist/generated/event-types.d.ts +9 -10
  179. package/dist/generated/eventRegistry.d.ts +3 -7
  180. package/dist/generated/server/server-exports.d.ts +19 -21
  181. package/dist/generated/server/server.cjs.map +1 -1
  182. package/dist/generated/server/server.d.ts +113 -87
  183. package/dist/generated/subgraph.cjs +797 -32
  184. package/dist/generated/subgraph.cjs.map +1 -1
  185. package/dist/generated/subgraph.d.ts +464 -332
  186. package/dist/generated/subgraph.js +792 -32
  187. package/dist/generated/subgraph.js.map +1 -1
  188. package/dist/index.browser.d.ts +47 -96
  189. package/dist/index.browser.js +12 -0
  190. package/dist/index.browser.js.map +1 -1
  191. package/dist/index.cjs +3 -1
  192. package/dist/index.cjs.map +1 -1
  193. package/dist/index.d.ts +0 -2
  194. package/dist/index.js +3 -1
  195. package/dist/index.js.map +1 -1
  196. package/dist/index.node.cjs +14 -3
  197. package/dist/index.node.cjs.map +1 -1
  198. package/dist/index.node.d.ts +203 -87
  199. package/dist/index.node.js +14 -2
  200. package/dist/index.node.js.map +1 -1
  201. package/dist/node.cjs.map +1 -1
  202. package/dist/node.d.ts +42 -2
  203. package/dist/node.js.map +1 -1
  204. package/dist/platform/browser-only.d.ts +5 -8
  205. package/dist/platform/browser-only.test.d.ts +1 -0
  206. package/dist/platform/browser-safe.d.ts +6 -9
  207. package/dist/platform/browser-safe.test.d.ts +1 -0
  208. package/dist/platform/browser.cjs +167 -8
  209. package/dist/platform/browser.cjs.map +1 -1
  210. package/dist/platform/browser.d.ts +235 -18
  211. package/dist/platform/browser.js +179 -29
  212. package/dist/platform/browser.js.map +1 -1
  213. package/dist/platform/browser.test.d.ts +1 -0
  214. package/dist/platform/index.d.ts +11 -5
  215. package/dist/platform/interface.cjs.map +1 -1
  216. package/dist/platform/interface.d.ts +289 -98
  217. package/dist/platform/node.cjs +163 -2
  218. package/dist/platform/node.cjs.map +1 -1
  219. package/dist/platform/node.d.ts +72 -13
  220. package/dist/platform/node.js +175 -21
  221. package/dist/platform/node.js.map +1 -1
  222. package/dist/platform/ports/openpgp-port.cjs +74 -0
  223. package/dist/platform/ports/openpgp-port.cjs.map +1 -0
  224. package/dist/platform/ports/openpgp-port.d.ts +13 -0
  225. package/dist/platform/ports/openpgp-port.js +59 -0
  226. package/dist/platform/ports/openpgp-port.js.map +1 -0
  227. package/dist/platform/ports/pgp-port.cjs +17 -0
  228. package/dist/platform/ports/pgp-port.cjs.map +1 -0
  229. package/dist/platform/ports/pgp-port.d.ts +35 -0
  230. package/dist/platform/ports/pgp-port.js +1 -0
  231. package/dist/platform/ports/pgp-port.js.map +1 -0
  232. package/dist/platform/shared/error-utils.d.ts +2 -4
  233. package/dist/platform/shared/pgp-utils.cjs +2 -2
  234. package/dist/platform/shared/pgp-utils.cjs.map +1 -1
  235. package/dist/platform/shared/pgp-utils.d.ts +3 -5
  236. package/dist/platform/shared/pgp-utils.js +2 -2
  237. package/dist/platform/shared/pgp-utils.js.map +1 -1
  238. package/dist/platform/shared/stream-utils.d.ts +1 -3
  239. package/dist/platform/utils.d.ts +6 -10
  240. package/dist/platform/utils.test.d.ts +1 -0
  241. package/dist/platform.browser.d.ts +9 -4
  242. package/dist/platform.d.ts +11 -5
  243. package/dist/platform.node.d.ts +10 -5
  244. package/dist/server/relayerHandler.cjs +337 -0
  245. package/dist/server/relayerHandler.cjs.map +1 -0
  246. package/dist/server/relayerHandler.d.ts +38 -0
  247. package/dist/server/relayerHandler.js +313 -0
  248. package/dist/server/relayerHandler.js.map +1 -0
  249. package/dist/storage/index.d.ts +56 -10
  250. package/dist/storage/manager.cjs +110 -27
  251. package/dist/storage/manager.cjs.map +1 -1
  252. package/dist/storage/manager.d.ts +121 -30
  253. package/dist/storage/manager.js +113 -37
  254. package/dist/storage/manager.js.map +1 -1
  255. package/dist/storage/providers/callback-storage.cjs +89 -18
  256. package/dist/storage/providers/callback-storage.cjs.map +1 -1
  257. package/dist/storage/providers/callback-storage.d.ts +111 -28
  258. package/dist/storage/providers/callback-storage.js +89 -18
  259. package/dist/storage/providers/callback-storage.js.map +1 -1
  260. package/dist/storage/providers/google-drive.cjs +2 -2
  261. package/dist/storage/providers/google-drive.cjs.map +1 -1
  262. package/dist/storage/providers/google-drive.d.ts +3 -7
  263. package/dist/storage/providers/google-drive.js +4 -7
  264. package/dist/storage/providers/google-drive.js.map +1 -1
  265. package/dist/storage/providers/google-drive.test.d.ts +1 -0
  266. package/dist/storage/providers/ipfs.cjs +5 -5
  267. package/dist/storage/providers/ipfs.cjs.map +1 -1
  268. package/dist/storage/providers/ipfs.d.ts +3 -6
  269. package/dist/storage/providers/ipfs.js +7 -10
  270. package/dist/storage/providers/ipfs.js.map +1 -1
  271. package/dist/storage/providers/pinata.cjs +6 -6
  272. package/dist/storage/providers/pinata.cjs.map +1 -1
  273. package/dist/storage/providers/pinata.d.ts +17 -22
  274. package/dist/storage/providers/pinata.js +8 -11
  275. package/dist/storage/providers/pinata.js.map +1 -1
  276. package/dist/storage/tests/callbackStorage.test.d.ts +1 -0
  277. package/dist/storage/tests/googleDriveStorage.test.d.ts +1 -0
  278. package/dist/storage/tests/ipfsStorage.test.d.ts +1 -0
  279. package/dist/storage/tests/pinataStorage.test.d.ts +1 -0
  280. package/dist/storage/tests/storageManager.test.d.ts +1 -0
  281. package/dist/tests/abi.test.d.ts +1 -0
  282. package/dist/tests/chains-definitions.test.d.ts +1 -0
  283. package/dist/tests/core-encryption.test.d.ts +1 -0
  284. package/dist/tests/core-extended.test.d.ts +1 -0
  285. package/dist/tests/core-generics-coverage.test.d.ts +1 -0
  286. package/dist/tests/coverage-boost.test.d.ts +1 -0
  287. package/dist/tests/crypto-cross-platform-compatibility.test.d.ts +1 -0
  288. package/dist/tests/data-addfile-permissions-schema.test.d.ts +1 -0
  289. package/dist/tests/data-additional-methods.test.d.ts +1 -0
  290. package/dist/tests/data-controller-edge-cases.test.d.ts +1 -0
  291. package/dist/tests/data-ipfs-gateways.test.d.ts +1 -0
  292. package/dist/tests/data-relayer.test.d.ts +1 -0
  293. package/dist/tests/data-schema-validation.test.d.ts +1 -0
  294. package/dist/tests/data-simple-methods.test.d.ts +1 -0
  295. package/dist/tests/data.test.d.ts +1 -0
  296. package/dist/tests/demo-integration.test.d.ts +1 -0
  297. package/dist/tests/demo-trusted-server-integration.test.d.ts +1 -0
  298. package/dist/tests/download-relayer.test.d.ts +1 -0
  299. package/dist/tests/dual-mode-permissions.test.d.ts +1 -0
  300. package/dist/tests/dual-mode-trusted-servers.test.d.ts +1 -0
  301. package/dist/tests/encryption-correct-implementation.test.d.ts +1 -0
  302. package/dist/tests/encryption-coverage.test.d.ts +1 -0
  303. package/dist/tests/encryption-edge-cases.test.d.ts +1 -0
  304. package/dist/tests/encryption-utils-updated.test.d.ts +1 -0
  305. package/dist/tests/errors-coverage.test.d.ts +1 -0
  306. package/dist/tests/errors.test.d.ts +1 -0
  307. package/dist/tests/factories/mockFactory.d.ts +316 -0
  308. package/dist/tests/fakes/FakeStorageManager.d.ts +200 -0
  309. package/dist/tests/fakes/FakeStorageManager.test.d.ts +1 -0
  310. package/dist/tests/fakes/FakeWaitForTransactionEvents.d.ts +170 -0
  311. package/dist/tests/fakes/FakeWaitForTransactionEvents.test.d.ts +1 -0
  312. package/dist/tests/fakes/fake-pgp-port.d.ts +13 -0
  313. package/dist/tests/grantValidation-edge-cases.test.d.ts +1 -0
  314. package/dist/tests/grantValidation-unreachable-branch.test.d.ts +1 -0
  315. package/dist/tests/helper-methods.test.d.ts +1 -0
  316. package/dist/tests/helpers/platformTestHelpers.d.ts +106 -0
  317. package/dist/tests/helpers/typedMocks.d.ts +64 -0
  318. package/dist/tests/index-browser.test.d.ts +1 -0
  319. package/dist/tests/index-node.test.d.ts +1 -0
  320. package/dist/tests/index.test.d.ts +1 -0
  321. package/dist/tests/mocks/platformAdapter.d.ts +12 -0
  322. package/dist/tests/new-permissions-methods.test.d.ts +1 -0
  323. package/dist/tests/no-buffer-browser.test.d.ts +1 -0
  324. package/dist/tests/permissions-grantee.test.d.ts +1 -0
  325. package/dist/tests/permissions-revoke-relayer.test.d.ts +1 -0
  326. package/dist/tests/permissions-schema-validation.test.d.ts +1 -0
  327. package/dist/tests/permissions-server-files.test.d.ts +1 -0
  328. package/dist/tests/permissions-transaction-options.test.d.ts +1 -0
  329. package/dist/tests/permissions-trust-servers.test.d.ts +1 -0
  330. package/dist/tests/permissions.test.d.ts +1 -0
  331. package/dist/tests/personal.test.d.ts +1 -0
  332. package/dist/tests/platform-browser.test.d.ts +1 -0
  333. package/dist/tests/platform-crypto-expanded.test.d.ts +1 -0
  334. package/dist/tests/platform-crypto.test.d.ts +1 -0
  335. package/dist/tests/platform-index.test.d.ts +1 -0
  336. package/dist/tests/platform-node.test.d.ts +1 -0
  337. package/dist/tests/platform-shared-utils.test.d.ts +1 -0
  338. package/dist/tests/platform-updated.test.d.ts +1 -0
  339. package/dist/tests/protocol-additional-methods.test.d.ts +1 -0
  340. package/dist/tests/protocol.test.d.ts +1 -0
  341. package/dist/tests/read-only-mode.test.d.ts +1 -0
  342. package/dist/tests/relayer-integration.test.d.ts +1 -0
  343. package/dist/tests/relayer-unified.test.d.ts +1 -0
  344. package/dist/tests/schemas.test.d.ts +1 -0
  345. package/dist/tests/server-relayer-handler.test.d.ts +1 -0
  346. package/dist/tests/setup.d.ts +7 -0
  347. package/dist/tests/signatureFormatter.test.d.ts +1 -0
  348. package/dist/tests/trusted-server-queries.test.d.ts +1 -0
  349. package/dist/tests/typedDataConverter.test.d.ts +1 -0
  350. package/dist/tests/types-contracts.test.d.ts +1 -0
  351. package/dist/tests/types-data.test.d.ts +1 -0
  352. package/dist/tests/types-external-apis.test.d.ts +1 -0
  353. package/dist/tests/types-generics.test.d.ts +1 -0
  354. package/dist/tests/types-permissions.test.d.ts +1 -0
  355. package/dist/tests/types-upload-params.test.d.ts +1 -0
  356. package/dist/tests/types.test.d.ts +1 -0
  357. package/dist/tests/utils-formatters.test.d.ts +1 -0
  358. package/dist/tests/utils-grantFiles-edge-cases.test.d.ts +1 -0
  359. package/dist/tests/utils-grantFiles-validation.test.d.ts +1 -0
  360. package/dist/tests/utils-grantFiles.test.d.ts +1 -0
  361. package/dist/tests/utils-grantValidation-consolidated.test.d.ts +1 -0
  362. package/dist/tests/utils-grants.test.d.ts +1 -0
  363. package/dist/tests/utils-ipfs-additional.test.d.ts +1 -0
  364. package/dist/tests/utils-ipfs.test.d.ts +4 -0
  365. package/dist/tests/utils-schemaValidation.test.d.ts +1 -0
  366. package/dist/tests/vana.test.d.ts +1 -0
  367. package/dist/tests/wallet-crypto-compatibility.test.d.ts +1 -0
  368. package/dist/types/blockchain.cjs.map +1 -1
  369. package/dist/types/blockchain.d.ts +46 -13
  370. package/dist/types/chains-additional.test.d.ts +1 -0
  371. package/dist/types/chains.cjs.map +1 -1
  372. package/dist/types/chains.d.ts +80 -16
  373. package/dist/types/chains.js.map +1 -1
  374. package/dist/types/config.cjs +10 -0
  375. package/dist/types/config.cjs.map +1 -1
  376. package/dist/types/config.d.ts +236 -242
  377. package/dist/types/config.js +8 -0
  378. package/dist/types/config.js.map +1 -1
  379. package/dist/types/contracts.cjs.map +1 -1
  380. package/dist/types/contracts.d.ts +79 -18
  381. package/dist/types/controller-context.cjs.map +1 -1
  382. package/dist/types/controller-context.d.ts +17 -21
  383. package/dist/types/data.cjs.map +1 -1
  384. package/dist/types/data.d.ts +111 -49
  385. package/dist/types/external-apis.d.ts +10 -12
  386. package/dist/types/generics.cjs.map +1 -1
  387. package/dist/types/generics.d.ts +116 -48
  388. package/dist/types/index.cjs +5 -4
  389. package/dist/types/index.cjs.map +1 -1
  390. package/dist/types/index.d.ts +47 -22
  391. package/dist/types/index.js +9 -2
  392. package/dist/types/index.js.map +1 -1
  393. package/dist/types/operations.cjs +2 -2
  394. package/dist/types/operations.cjs.map +1 -1
  395. package/dist/types/operations.d.ts +178 -32
  396. package/dist/types/operations.js +2 -2
  397. package/dist/types/operations.js.map +1 -1
  398. package/dist/types/options.cjs +17 -0
  399. package/dist/types/options.cjs.map +1 -0
  400. package/dist/types/options.d.ts +213 -0
  401. package/dist/types/options.js +1 -0
  402. package/dist/types/options.js.map +1 -0
  403. package/dist/types/permissions.cjs.map +1 -1
  404. package/dist/types/permissions.d.ts +72 -78
  405. package/dist/types/personal.cjs.map +1 -1
  406. package/dist/types/personal.d.ts +137 -22
  407. package/dist/types/relayer.cjs.map +1 -1
  408. package/dist/types/relayer.d.ts +293 -50
  409. package/dist/types/storage.cjs.map +1 -1
  410. package/dist/types/storage.d.ts +15 -29
  411. package/dist/types/storage.js +2 -5
  412. package/dist/types/storage.js.map +1 -1
  413. package/dist/types/transactionResults.d.ts +16 -18
  414. package/dist/types/utils.cjs.map +1 -1
  415. package/dist/types/utils.d.ts +20 -68
  416. package/dist/types.d.ts +4 -28
  417. package/dist/utils/__tests__/parseTransaction.test.d.ts +1 -0
  418. package/dist/utils/__tests__/pojo-serialization.test.d.ts +1 -0
  419. package/dist/utils/__tests__/signatureCache.test.d.ts +1 -0
  420. package/dist/utils/__tests__/subgraphConsistency.test.d.ts +4 -0
  421. package/dist/utils/__tests__/subgraphPagination.test.d.ts +4 -0
  422. package/dist/utils/__tests__/transaction-edge-cases.test.d.ts +1 -0
  423. package/dist/utils/__tests__/transactionHelpers.test.d.ts +1 -0
  424. package/dist/utils/__tests__/urlResolver.test.d.ts +4 -0
  425. package/dist/utils/blockchain/registry.cjs +2 -2
  426. package/dist/utils/blockchain/registry.cjs.map +1 -1
  427. package/dist/utils/blockchain/registry.d.ts +6 -8
  428. package/dist/utils/blockchain/registry.js +2 -2
  429. package/dist/utils/blockchain/registry.js.map +1 -1
  430. package/dist/utils/blockchain/registry.test.d.ts +1 -0
  431. package/dist/utils/chainQuery.cjs +107 -0
  432. package/dist/utils/chainQuery.cjs.map +1 -0
  433. package/dist/utils/chainQuery.d.ts +31 -0
  434. package/dist/utils/chainQuery.js +82 -0
  435. package/dist/utils/chainQuery.js.map +1 -0
  436. package/dist/utils/crypto-utils.cjs +0 -12
  437. package/dist/utils/crypto-utils.cjs.map +1 -1
  438. package/dist/utils/crypto-utils.d.ts +9 -27
  439. package/dist/utils/crypto-utils.js +0 -11
  440. package/dist/utils/crypto-utils.js.map +1 -1
  441. package/dist/utils/crypto-utils.test.d.ts +1 -0
  442. package/dist/utils/download.cjs +3 -3
  443. package/dist/utils/download.cjs.map +1 -1
  444. package/dist/utils/download.d.ts +13 -14
  445. package/dist/utils/download.js +2 -2
  446. package/dist/utils/download.js.map +1 -1
  447. package/dist/utils/encoding.cjs +1 -1
  448. package/dist/utils/encoding.cjs.map +1 -1
  449. package/dist/utils/encoding.d.ts +4 -6
  450. package/dist/utils/encoding.js +1 -1
  451. package/dist/utils/encoding.js.map +1 -1
  452. package/dist/utils/encoding.test.d.ts +1 -0
  453. package/dist/utils/encryption.cjs +16 -10
  454. package/dist/utils/encryption.cjs.map +1 -1
  455. package/dist/utils/encryption.d.ts +13 -17
  456. package/dist/utils/encryption.js +16 -10
  457. package/dist/utils/encryption.js.map +1 -1
  458. package/dist/utils/formatters.cjs +4 -2
  459. package/dist/utils/formatters.cjs.map +1 -1
  460. package/dist/utils/formatters.d.ts +4 -6
  461. package/dist/utils/formatters.js +4 -2
  462. package/dist/utils/formatters.js.map +1 -1
  463. package/dist/utils/grantFiles.cjs +7 -4
  464. package/dist/utils/grantFiles.cjs.map +1 -1
  465. package/dist/utils/grantFiles.d.ts +16 -30
  466. package/dist/utils/grantFiles.js +7 -4
  467. package/dist/utils/grantFiles.js.map +1 -1
  468. package/dist/utils/grantValidation.cjs +1 -1
  469. package/dist/utils/grantValidation.cjs.map +1 -1
  470. package/dist/utils/grantValidation.d.ts +109 -33
  471. package/dist/utils/grantValidation.js +1 -1
  472. package/dist/utils/grantValidation.js.map +1 -1
  473. package/dist/utils/grants.cjs +1 -1
  474. package/dist/utils/grants.cjs.map +1 -1
  475. package/dist/utils/grants.d.ts +101 -23
  476. package/dist/utils/grants.js +1 -1
  477. package/dist/utils/grants.js.map +1 -1
  478. package/dist/utils/ipfs.cjs +2 -4
  479. package/dist/utils/ipfs.cjs.map +1 -1
  480. package/dist/utils/ipfs.d.ts +8 -10
  481. package/dist/utils/ipfs.js +2 -4
  482. package/dist/utils/ipfs.js.map +1 -1
  483. package/dist/utils/lazy-import.cjs +4 -6
  484. package/dist/utils/lazy-import.cjs.map +1 -1
  485. package/dist/utils/lazy-import.d.ts +33 -10
  486. package/dist/utils/lazy-import.js +4 -6
  487. package/dist/utils/lazy-import.js.map +1 -1
  488. package/dist/utils/multicall.cjs +4 -2
  489. package/dist/utils/multicall.cjs.map +1 -1
  490. package/dist/utils/multicall.d.ts +5 -8
  491. package/dist/utils/multicall.js +4 -2
  492. package/dist/utils/multicall.js.map +1 -1
  493. package/dist/utils/parseTransactionPojo.cjs.map +1 -1
  494. package/dist/utils/parseTransactionPojo.d.ts +4 -10
  495. package/dist/utils/parseTransactionPojo.js.map +1 -1
  496. package/dist/utils/schemaValidation.cjs +5 -5
  497. package/dist/utils/schemaValidation.cjs.map +1 -1
  498. package/dist/utils/schemaValidation.d.ts +8 -12
  499. package/dist/utils/schemaValidation.js +7 -10
  500. package/dist/utils/schemaValidation.js.map +1 -1
  501. package/dist/utils/signatureCache.cjs +9 -4
  502. package/dist/utils/signatureCache.cjs.map +1 -1
  503. package/dist/utils/signatureCache.d.ts +53 -15
  504. package/dist/utils/signatureCache.js +12 -10
  505. package/dist/utils/signatureCache.js.map +1 -1
  506. package/dist/utils/signatureFormatter.cjs +6 -9
  507. package/dist/utils/signatureFormatter.cjs.map +1 -1
  508. package/dist/utils/signatureFormatter.d.ts +2 -5
  509. package/dist/utils/signatureFormatter.js +6 -9
  510. package/dist/utils/signatureFormatter.js.map +1 -1
  511. package/dist/utils/subgraphConsistency.cjs +184 -0
  512. package/dist/utils/subgraphConsistency.cjs.map +1 -0
  513. package/dist/utils/subgraphConsistency.d.ts +65 -0
  514. package/dist/utils/subgraphConsistency.js +155 -0
  515. package/dist/utils/subgraphConsistency.js.map +1 -0
  516. package/dist/utils/subgraphMetaCache.cjs +101 -0
  517. package/dist/utils/subgraphMetaCache.cjs.map +1 -0
  518. package/dist/utils/subgraphMetaCache.d.ts +56 -0
  519. package/dist/utils/subgraphMetaCache.js +76 -0
  520. package/dist/utils/subgraphMetaCache.js.map +1 -0
  521. package/dist/utils/subgraphPagination.cjs +104 -0
  522. package/dist/utils/subgraphPagination.cjs.map +1 -0
  523. package/dist/utils/subgraphPagination.d.ts +78 -0
  524. package/dist/utils/subgraphPagination.js +78 -0
  525. package/dist/utils/subgraphPagination.js.map +1 -0
  526. package/dist/utils/tests/multicall.test.d.ts +1 -0
  527. package/dist/utils/transactionHelpers.cjs.map +1 -1
  528. package/dist/utils/transactionHelpers.d.ts +17 -23
  529. package/dist/utils/transactionHelpers.js.map +1 -1
  530. package/dist/utils/typeGuards.cjs +109 -0
  531. package/dist/utils/typeGuards.cjs.map +1 -0
  532. package/dist/utils/typeGuards.d.ts +138 -0
  533. package/dist/utils/typeGuards.js +74 -0
  534. package/dist/utils/typeGuards.js.map +1 -0
  535. package/dist/utils/typedDataConverter.cjs.map +1 -1
  536. package/dist/utils/typedDataConverter.d.ts +42 -9
  537. package/dist/utils/typedDataConverter.js.map +1 -1
  538. package/dist/utils/urlResolver.cjs +8 -1
  539. package/dist/utils/urlResolver.cjs.map +1 -1
  540. package/dist/utils/urlResolver.d.ts +24 -8
  541. package/dist/utils/urlResolver.js +9 -2
  542. package/dist/utils/urlResolver.js.map +1 -1
  543. package/dist/utils/wallet.cjs +63 -0
  544. package/dist/utils/wallet.cjs.map +1 -0
  545. package/dist/utils/wallet.d.ts +94 -0
  546. package/dist/utils/wallet.js +37 -0
  547. package/dist/utils/wallet.js.map +1 -0
  548. package/dist/utils/withEvents.cjs.map +1 -1
  549. package/dist/utils/withEvents.d.ts +5 -12
  550. package/dist/utils/withEvents.js.map +1 -1
  551. package/package.json +24 -16
  552. package/dist/browser.d.cts +0 -2
  553. package/dist/chains/definitions.d.cts +0 -53
  554. package/dist/chains/index.d.cts +0 -2
  555. package/dist/chains.browser.cjs +0 -37
  556. package/dist/chains.browser.cjs.map +0 -1
  557. package/dist/chains.browser.d.cts +0 -2
  558. package/dist/chains.d.cts +0 -2
  559. package/dist/chains.node.d.cts +0 -2
  560. package/dist/config/addresses.d.cts +0 -401
  561. package/dist/config/chains.d.cts +0 -85
  562. package/dist/config/features.d.cts +0 -64
  563. package/dist/contracts/contractController.d.cts +0 -117
  564. package/dist/controllers/data.d.cts +0 -915
  565. package/dist/controllers/permissions.d.cts +0 -1383
  566. package/dist/controllers/protocol.d.cts +0 -188
  567. package/dist/controllers/schemas.d.cts +0 -260
  568. package/dist/controllers/server.d.cts +0 -230
  569. package/dist/core/apiClient.d.cts +0 -165
  570. package/dist/core/client.d.cts +0 -92
  571. package/dist/core/generics.d.cts +0 -120
  572. package/dist/core.d.cts +0 -493
  573. package/dist/crypto/ecies/__tests__/test-vectors.d.cts +0 -40
  574. package/dist/crypto/ecies/base.d.cts +0 -143
  575. package/dist/crypto/ecies/browser.d.cts +0 -48
  576. package/dist/crypto/ecies/constants.d.cts +0 -122
  577. package/dist/crypto/ecies/index.d.cts +0 -1
  578. package/dist/crypto/ecies/interface.d.cts +0 -176
  579. package/dist/crypto/ecies/node.d.cts +0 -50
  580. package/dist/crypto/ecies/test-vectors/eccrypto-vectors.d.cts +0 -76
  581. package/dist/crypto/ecies/test-vectors/eccrypto-vectors.d.ts +0 -76
  582. package/dist/crypto/ecies/utils.d.cts +0 -67
  583. package/dist/crypto/services/WalletKeyEncryptionService.d.cts +0 -92
  584. package/dist/diagnostics.d.cts +0 -26
  585. package/dist/errors.d.cts +0 -350
  586. package/dist/generated/abi/ComputeEngineImplementation.d.cts +0 -996
  587. package/dist/generated/abi/ComputeInstructionRegistryImplementation.d.cts +0 -545
  588. package/dist/generated/abi/DATFactoryImplementation.d.cts +0 -661
  589. package/dist/generated/abi/DATImplementation.d.cts +0 -693
  590. package/dist/generated/abi/DATPausableImplementation.d.cts +0 -1145
  591. package/dist/generated/abi/DATVotesImplementation.d.cts +0 -1095
  592. package/dist/generated/abi/DLPPerformanceImplementation.d.cts +0 -883
  593. package/dist/generated/abi/DLPRegistryImplementation.d.cts +0 -1123
  594. package/dist/generated/abi/DLPRegistryTreasuryImplementation.d.cts +0 -452
  595. package/dist/generated/abi/DLPRewardDeployerImplementation.d.cts +0 -714
  596. package/dist/generated/abi/DLPRewardDeployerTreasuryImplementation.d.cts +0 -452
  597. package/dist/generated/abi/DLPRewardSwapImplementation.d.cts +0 -706
  598. package/dist/generated/abi/DLPRootImplementation.d.cts +0 -1248
  599. package/dist/generated/abi/DLPTreasuryImplementation.d.cts +0 -452
  600. package/dist/generated/abi/DataLiquidityPoolImplementation.d.cts +0 -737
  601. package/dist/generated/abi/DataPortabilityGranteesImplementation.d.cts +0 -661
  602. package/dist/generated/abi/DataPortabilityPermissionsImplementation.d.cts +0 -989
  603. package/dist/generated/abi/DataPortabilityServersImplementation.d.cts +0 -1086
  604. package/dist/generated/abi/DataRefinerRegistryImplementation.d.cts +0 -737
  605. package/dist/generated/abi/DataRegistryImplementation.d.cts +0 -1014
  606. package/dist/generated/abi/QueryEngineImplementation.d.cts +0 -1001
  607. package/dist/generated/abi/SwapHelperImplementation.d.cts +0 -764
  608. package/dist/generated/abi/TeePoolDedicatedGpuImplementation.d.cts +0 -701
  609. package/dist/generated/abi/TeePoolDedicatedStandardImplementation.d.cts +0 -701
  610. package/dist/generated/abi/TeePoolEphemeralStandardImplementation.d.cts +0 -701
  611. package/dist/generated/abi/TeePoolImplementation.d.cts +0 -993
  612. package/dist/generated/abi/TeePoolPersistentGpuImplementation.d.cts +0 -701
  613. package/dist/generated/abi/TeePoolPersistentStandardImplementation.d.cts +0 -701
  614. package/dist/generated/abi/TeePoolPhalaImplementation.d.cts +0 -993
  615. package/dist/generated/abi/VanaEpochImplementation.d.cts +0 -900
  616. package/dist/generated/abi/VanaPoolEntityImplementation.d.cts +0 -934
  617. package/dist/generated/abi/VanaPoolStakingImplementation.d.cts +0 -693
  618. package/dist/generated/abi/VanaPoolTreasuryImplementation.d.cts +0 -394
  619. package/dist/generated/abi/index.d.cts +0 -26547
  620. package/dist/generated/event-types.d.cts +0 -855
  621. package/dist/generated/eventRegistry.d.cts +0 -18
  622. package/dist/generated/server/server-exports.d.cts +0 -21
  623. package/dist/generated/server/server.d.cts +0 -512
  624. package/dist/generated/subgraph.d.cts +0 -5981
  625. package/dist/index.browser.cjs +0 -151
  626. package/dist/index.browser.cjs.map +0 -1
  627. package/dist/index.browser.d.cts +0 -201
  628. package/dist/index.d.cts +0 -2
  629. package/dist/index.node.d.cts +0 -87
  630. package/dist/node.d.cts +0 -2
  631. package/dist/platform/browser-only.d.cts +0 -25
  632. package/dist/platform/browser-safe.d.cts +0 -32
  633. package/dist/platform/browser.d.cts +0 -74
  634. package/dist/platform/index.d.cts +0 -5
  635. package/dist/platform/interface.d.cts +0 -218
  636. package/dist/platform/node.d.cts +0 -27
  637. package/dist/platform/shared/error-utils.d.cts +0 -25
  638. package/dist/platform/shared/pgp-utils.d.cts +0 -61
  639. package/dist/platform/shared/stream-utils.d.cts +0 -16
  640. package/dist/platform/utils.d.cts +0 -53
  641. package/dist/platform.browser.cjs +0 -41
  642. package/dist/platform.browser.cjs.map +0 -1
  643. package/dist/platform.browser.d.cts +0 -4
  644. package/dist/platform.d.cts +0 -5
  645. package/dist/platform.node.d.cts +0 -5
  646. package/dist/schemas/dataSchema.schema.d.cts +0 -88
  647. package/dist/schemas/dataSchema.schema.d.ts +0 -88
  648. package/dist/schemas/grantFile.schema.d.cts +0 -57
  649. package/dist/schemas/grantFile.schema.d.ts +0 -57
  650. package/dist/server/handler.cjs +0 -101
  651. package/dist/server/handler.cjs.map +0 -1
  652. package/dist/server/handler.d.cts +0 -306
  653. package/dist/server/handler.d.ts +0 -306
  654. package/dist/server/handler.js +0 -77
  655. package/dist/server/handler.js.map +0 -1
  656. package/dist/storage/index.d.cts +0 -10
  657. package/dist/storage/manager.d.cts +0 -150
  658. package/dist/storage/providers/callback-storage.d.cts +0 -100
  659. package/dist/storage/providers/google-drive.d.cts +0 -156
  660. package/dist/storage/providers/ipfs.d.cts +0 -163
  661. package/dist/storage/providers/pinata.d.cts +0 -173
  662. package/dist/types/blockchain.d.cts +0 -52
  663. package/dist/types/chains.d.cts +0 -34
  664. package/dist/types/config.d.cts +0 -726
  665. package/dist/types/contracts.d.cts +0 -68
  666. package/dist/types/controller-context.d.cts +0 -71
  667. package/dist/types/data.d.cts +0 -694
  668. package/dist/types/eccrypto-js.d.d.cts +0 -13
  669. package/dist/types/eccrypto-js.d.d.ts +0 -13
  670. package/dist/types/external-apis.d.cts +0 -186
  671. package/dist/types/generics.d.cts +0 -450
  672. package/dist/types/index.d.cts +0 -22
  673. package/dist/types/operations.d.cts +0 -116
  674. package/dist/types/permissions.d.cts +0 -957
  675. package/dist/types/personal.d.cts +0 -40
  676. package/dist/types/relayer.d.cts +0 -284
  677. package/dist/types/storage.d.cts +0 -131
  678. package/dist/types/transactionResults.d.cts +0 -195
  679. package/dist/types/utils.d.cts +0 -819
  680. package/dist/types.d.cts +0 -54
  681. package/dist/utils/blockchain/registry.d.cts +0 -34
  682. package/dist/utils/crypto-utils.d.cts +0 -118
  683. package/dist/utils/download.d.cts +0 -41
  684. package/dist/utils/encoding.d.cts +0 -54
  685. package/dist/utils/encryption.d.cts +0 -275
  686. package/dist/utils/formatters.d.cts +0 -120
  687. package/dist/utils/grantFiles.d.cts +0 -186
  688. package/dist/utils/grantValidation.d.cts +0 -150
  689. package/dist/utils/grants.d.cts +0 -70
  690. package/dist/utils/ipfs.d.cts +0 -90
  691. package/dist/utils/lazy-import.d.cts +0 -20
  692. package/dist/utils/multicall.d.cts +0 -129
  693. package/dist/utils/parseTransactionPojo.d.cts +0 -37
  694. package/dist/utils/schemaValidation.d.cts +0 -172
  695. package/dist/utils/signatureCache.d.cts +0 -134
  696. package/dist/utils/signatureFormatter.d.cts +0 -39
  697. package/dist/utils/transactionHelpers.d.cts +0 -86
  698. package/dist/utils/typedDataConverter.d.cts +0 -13
  699. package/dist/utils/urlResolver.d.cts +0 -40
  700. package/dist/utils/withEvents.d.cts +0 -63
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/multicall.ts"],"sourcesContent":["import type {\n Address,\n PublicClient,\n MulticallParameters,\n MulticallReturnType,\n EncodeFunctionDataParameters,\n Hex,\n Abi,\n} from \"viem\";\nimport { encodeFunctionData, size } from \"viem\";\nimport { getUtilityAddress } from \"../config/addresses\";\nimport type { VanaChainId } from \"../types\";\n\n/**\n * Type for a contract function configuration used in multicall\n */\nexport interface ContractFunctionConfig {\n address: Address;\n abi: Abi;\n functionName: string;\n args?: readonly unknown[];\n}\n\n/**\n * Configuration options for gas-aware multicall batching.\n *\n * @remarks\n * These options control how the multicall utility splits large batches\n * to stay within gas and calldata limits. The defaults are conservative\n * to ensure compatibility across different chains and RPC providers.\n */\nexport interface GasAwareMulticallOptions {\n /**\n * Maximum gas per batch. Defaults to 10M (conservative for most chains).\n *\n * @remarks\n * This should be set below the block gas limit of your target chain.\n * Common values:\n * - Vana mainnet: 30M (use 25M for safety)\n * - Vana moksha: 30M (use 25M for safety)\n * - Ethereum mainnet: 30M (use 25M for safety)\n * - Arbitrum: 32M (use 25M for safety)\n */\n maxGasPerBatch?: bigint;\n\n /**\n * Maximum calldata size per batch in bytes. Defaults to 100KB.\n *\n * @remarks\n * This is particularly important for L2 chains where calldata is expensive.\n * Some RPC providers also have limits on request size.\n */\n maxCalldataBytes?: number;\n\n /**\n * How often to checkpoint gas estimates. Defaults to every 32 calls or 8KB.\n *\n * @remarks\n * More frequent checkpoints give more accurate batching but require more\n * RPC calls for gas estimation. The default balances accuracy vs performance.\n */\n checkpointFrequency?: {\n /** Checkpoint after this many calls */\n calls: number;\n /** Checkpoint after this many bytes of calldata */\n bytes: number;\n };\n\n /**\n * Whether to allow partial batch failures. Defaults to false.\n *\n * @remarks\n * When true, individual call failures won't fail the entire batch.\n * This matches viem's multicall behavior with allowFailure option.\n */\n allowFailure?: boolean;\n\n /**\n * Optional multicall3 contract address override.\n *\n * @remarks\n * By default, uses the standard multicall3 address deployed on most chains:\n * 0xcA11bde05977b3631167028862bE2a173976CA11\n */\n multicallAddress?: Address;\n\n /**\n * Optional callback for tracking batching progress.\n *\n * @remarks\n * Useful for showing progress in UI or debugging batch performance.\n */\n onProgress?: (completed: number, total: number) => void;\n}\n\n/**\n * Internal configuration with defaults applied\n */\ninterface NormalizedOptions {\n maxGasPerBatch: bigint;\n maxCalldataBytes: number;\n checkpointFrequency: {\n calls: number;\n bytes: number;\n };\n allowFailure: boolean;\n multicallAddress: Address;\n onProgress?: (completed: number, total: number) => void;\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULT_OPTIONS: Omit<NormalizedOptions, \"multicallAddress\"> = {\n maxGasPerBatch: 10_000_000n, // 10M gas - conservative default\n maxCalldataBytes: 100_000, // 100KB - works with most RPC providers\n checkpointFrequency: {\n calls: 32,\n bytes: 8192, // 8KB\n },\n allowFailure: false,\n};\n\n/**\n * A gas-aware multicall function that automatically batches calls to stay within limits.\n *\n * @remarks\n * This function extends viem's multicall with intelligent batching based on:\n * - Actual gas costs (via periodic estimateGas calls)\n * - Calldata size limits\n * - Chain-specific constraints\n *\n * It uses a greedy algorithm with periodic checkpoints to efficiently determine\n * optimal batch sizes without making excessive RPC calls.\n *\n * @param client - The viem public client to use for RPC calls\n * @param parameters - The multicall parameters (same as viem's multicall)\n * @param options - Optional configuration for gas-aware batching\n * @returns The aggregated results from all batches\n *\n * @example\n * ```typescript\n * // Basic usage - drop-in replacement for viem's multicall\n * const results = await gasAwareMulticall(publicClient, {\n * contracts: [\n * { address: '0x...', abi: erc20Abi, functionName: 'balanceOf', args: [address1] },\n * { address: '0x...', abi: erc20Abi, functionName: 'balanceOf', args: [address2] },\n * // ... hundreds more calls\n * ]\n * });\n *\n * // With custom limits for a specific chain\n * const results = await gasAwareMulticall(publicClient, {\n * contracts: calls,\n * }, {\n * maxGasPerBatch: 25_000_000n, // 25M for mainnet\n * maxCalldataBytes: 128_000, // 128KB\n * onProgress: (done, total) => console.log(`Progress: ${done}/${total}`)\n * });\n * ```\n */\nexport async function gasAwareMulticall<\n TContracts extends readonly ContractFunctionConfig[],\n TAllowFailure extends boolean = false,\n>(\n client: PublicClient,\n parameters: MulticallParameters<TContracts, TAllowFailure>,\n options: GasAwareMulticallOptions = {},\n): Promise<MulticallReturnType<TContracts, TAllowFailure>> {\n // Get the chain-specific Multicall3 address\n const chainId = await client.getChainId();\n const multicall3Address =\n options.multicallAddress ||\n getUtilityAddress(chainId as VanaChainId, \"Multicall3\");\n\n // Normalize options with defaults\n const opts: NormalizedOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n multicallAddress: multicall3Address,\n checkpointFrequency: {\n ...DEFAULT_OPTIONS.checkpointFrequency,\n ...options.checkpointFrequency,\n },\n };\n\n // Override allowFailure if specified in parameters\n if (parameters.allowFailure !== undefined) {\n opts.allowFailure = parameters.allowFailure;\n }\n\n const { contracts } = parameters;\n if (!contracts || contracts.length === 0) {\n return [] as unknown as MulticallReturnType<TContracts, TAllowFailure>;\n }\n\n // Execute batching algorithm\n const batches = await createBatches(\n client,\n contracts as readonly ContractFunctionConfig[],\n opts,\n );\n\n // Execute all batches in parallel\n const batchResults = await Promise.all(\n batches.map((batch, index) => {\n // Report progress if callback provided\n if (opts.onProgress && index > 0) {\n const completed = batches\n .slice(0, index)\n .reduce((sum, b) => sum + b.length, 0);\n opts.onProgress(completed, contracts.length);\n }\n\n // Execute batch using viem's multicall\n return client.multicall({\n ...parameters,\n contracts: batch as typeof contracts,\n multicallAddress: opts.multicallAddress,\n allowFailure: opts.allowFailure,\n });\n }),\n );\n\n // Report final progress\n if (opts.onProgress) {\n opts.onProgress(contracts.length, contracts.length);\n }\n\n // Flatten results\n return batchResults.flat() as MulticallReturnType<TContracts, TAllowFailure>;\n}\n\n/**\n * Creates optimally-sized batches using greedy algorithm with checkpoints.\n *\n * @param client - The viem public client for making RPC calls\n * @param contracts - Array of contract function configurations to batch\n * @param options - Normalized batching options with limits and settings\n * @returns Array of optimally-sized contract function configuration batches\n */\nasync function createBatches(\n client: PublicClient,\n contracts: readonly ContractFunctionConfig[],\n options: NormalizedOptions,\n): Promise<ContractFunctionConfig[][]> {\n const batches: ContractFunctionConfig[][] = [];\n let currentBatch: ContractFunctionConfig[] = [];\n let currentBytes = 0;\n let lastCheckpointIndex = 0;\n let lastCheckpointBytes = 0;\n let lastEstimatedGas = 0n;\n\n for (let i = 0; i < contracts.length; i++) {\n const contract = contracts[i];\n\n // Calculate encoded size for this call\n const encoded = encodeContractCall(contract);\n const callBytes = size(encoded);\n\n // Check if we need a gas checkpoint\n const callsSinceCheckpoint = i - lastCheckpointIndex;\n const bytesSinceCheckpoint = currentBytes - lastCheckpointBytes;\n\n const needsCheckpoint =\n callsSinceCheckpoint >= options.checkpointFrequency.calls ||\n bytesSinceCheckpoint >= options.checkpointFrequency.bytes;\n\n // Perform checkpoint if needed\n if (needsCheckpoint && currentBatch.length > 0) {\n try {\n lastEstimatedGas = await estimateBatchGas(\n client,\n currentBatch,\n options.multicallAddress,\n );\n lastCheckpointIndex = i;\n lastCheckpointBytes = currentBytes;\n } catch (error) {\n // If estimation fails, finalize current batch to be safe\n if (currentBatch.length > 1) {\n // Try with half the batch\n const halfBatch = currentBatch.slice(\n 0,\n Math.floor(currentBatch.length / 2),\n );\n batches.push(halfBatch);\n currentBatch = currentBatch.slice(halfBatch.length);\n currentBytes = calculateBatchSize(currentBatch);\n lastCheckpointIndex = i;\n lastCheckpointBytes = currentBytes;\n lastEstimatedGas = 0n;\n } else {\n // Single call failed, skip it or throw based on allowFailure\n if (!options.allowFailure) {\n throw new Error(`Gas estimation failed for call ${i}: ${error}`);\n }\n currentBatch = [];\n currentBytes = 0;\n continue;\n }\n }\n }\n\n // Check if adding this call would exceed limits\n const wouldExceedCalldata =\n currentBytes + callBytes > options.maxCalldataBytes;\n const wouldExceedGas =\n lastEstimatedGas > 0n &&\n estimateNextGas(lastEstimatedGas, callsSinceCheckpoint + 1) >\n options.maxGasPerBatch;\n\n // If we would exceed limits, finalize current batch\n if ((wouldExceedCalldata || wouldExceedGas) && currentBatch.length > 0) {\n batches.push(currentBatch);\n currentBatch = [];\n currentBytes = 0;\n lastCheckpointIndex = i;\n lastCheckpointBytes = 0;\n lastEstimatedGas = 0n;\n }\n\n // Add call to current batch\n currentBatch.push(contract);\n currentBytes += callBytes;\n }\n\n // Add final batch if not empty\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n }\n\n return batches;\n}\n\n/**\n * Encodes a contract call to measure its calldata size.\n *\n * @param contract - The contract function configuration to encode\n * @returns Hex-encoded function data\n */\nfunction encodeContractCall(contract: ContractFunctionConfig): Hex {\n const { abi, functionName, args } = contract;\n\n return encodeFunctionData({\n abi,\n functionName,\n args,\n } as EncodeFunctionDataParameters);\n}\n\n/**\n * Calculates total encoded size of a batch.\n *\n * @param batch - Array of contract function configurations to measure\n * @returns Total size in bytes of all encoded calls in the batch\n */\nfunction calculateBatchSize(batch: ContractFunctionConfig[]): number {\n return batch.reduce((total, contract) => {\n const encoded = encodeContractCall(contract);\n return total + size(encoded);\n }, 0);\n}\n\n/**\n * Estimates gas for a batch of calls via multicall3.\n *\n * @param client - The viem public client for gas estimation\n * @param batch - Array of contract calls to estimate gas for\n * @param multicallAddress - The multicall3 contract address to use\n * @returns Estimated gas cost for executing the batch\n */\nasync function estimateBatchGas(\n client: PublicClient,\n batch: ContractFunctionConfig[],\n multicallAddress: Address,\n): Promise<bigint> {\n // Encode batch as multicall3 aggregate3 call\n const calls = batch.map((contract) => ({\n target: contract.address,\n allowFailure: false,\n callData: encodeContractCall(contract),\n }));\n\n // Estimate gas for the multicall\n const gas = await client.estimateGas({\n to: multicallAddress,\n data: encodeFunctionData({\n abi: multicall3Abi,\n functionName: \"aggregate3\",\n args: [calls],\n }),\n });\n\n return gas;\n}\n\n/**\n * Extrapolates gas usage for calls added since last checkpoint.\n *\n * @remarks\n * Uses a conservative 1.1x multiplier for safety to account for gas usage variations.\n *\n * @param lastGas - The gas estimate from the last checkpoint\n * @param callsSinceCheckpoint - Number of calls added since the checkpoint\n * @returns Extrapolated gas estimate with safety margin\n */\nfunction estimateNextGas(\n lastGas: bigint,\n callsSinceCheckpoint: number,\n): bigint {\n if (callsSinceCheckpoint === 0) return lastGas;\n\n // Assume linear scaling with safety factor\n const avgGasPerCall = lastGas / BigInt(Math.max(1, callsSinceCheckpoint - 1));\n const estimatedGas = lastGas + avgGasPerCall;\n\n // Apply 10% safety margin\n return (estimatedGas * 110n) / 100n;\n}\n\n/**\n * Minimal multicall3 ABI for gas estimation\n */\nconst multicall3Abi = [\n {\n name: \"aggregate3\",\n type: \"function\",\n stateMutability: \"payable\",\n inputs: [\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"allowFailure\", type: \"bool\" },\n { name: \"callData\", type: \"bytes\" },\n ],\n },\n ],\n outputs: [\n {\n name: \"returnData\",\n type: \"tuple[]\",\n components: [\n { name: \"success\", type: \"bool\" },\n { name: \"returnData\", type: \"bytes\" },\n ],\n },\n ],\n },\n] as const;\n\n/**\n * Utility function to analyze calls and predict optimal batch configuration\n *\n * @remarks\n * This function helps determine the best configuration for a specific set of calls\n * by analyzing their characteristics. Useful for optimizing repeated operations.\n *\n * @param contracts - The calls to analyze\n * @returns Suggested configuration based on call analysis\n */\nexport function analyzeCallsForOptimalConfig(\n contracts: readonly ContractFunctionConfig[],\n): Pick<GasAwareMulticallOptions, \"checkpointFrequency\" | \"maxCalldataBytes\"> {\n // Calculate average call size\n const totalBytes = contracts.reduce((sum, contract) => {\n const encoded = encodeContractCall(contract);\n return sum + size(encoded);\n }, 0);\n\n const avgBytesPerCall = totalBytes / contracts.length;\n\n // Suggest checkpoint frequency based on call density\n const checkpointFrequency = {\n calls: avgBytesPerCall > 500 ? 16 : 32, // More frequent for large calls\n bytes: avgBytesPerCall > 500 ? 4096 : 8192,\n };\n\n // Suggest calldata limit based on total size\n // For 1000 calls with small arrays, totalBytes will be much less than 500KB,\n // so use number of contracts as additional signal\n const maxCalldataBytes =\n totalBytes > 50_000 || contracts.length > 500 ? 128_000 : 100_000;\n\n return {\n checkpointFrequency,\n maxCalldataBytes,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/utils/multicall.ts"],"sourcesContent":["import type {\n Address,\n PublicClient,\n MulticallParameters,\n MulticallReturnType,\n EncodeFunctionDataParameters,\n Hex,\n Abi,\n} from \"viem\";\nimport { encodeFunctionData, size } from \"viem\";\nimport { getUtilityAddress } from \"../config/addresses\";\nimport type { VanaChainId } from \"../types\";\n\n/**\n * Type for a contract function configuration used in multicall\n */\nexport interface ContractFunctionConfig {\n address: Address;\n abi: Abi;\n functionName: string;\n args?: readonly unknown[];\n}\n\n/**\n * Configuration options for gas-aware multicall batching.\n *\n * @remarks\n * These options control how the multicall utility splits large batches\n * to stay within gas and calldata limits. The defaults are conservative\n * to ensure compatibility across different chains and RPC providers.\n */\nexport interface GasAwareMulticallOptions {\n /**\n * Maximum gas per batch. Defaults to 10M (conservative for most chains).\n *\n * @remarks\n * This should be set below the block gas limit of your target chain.\n * Common values:\n * - Vana mainnet: 30M (use 25M for safety)\n * - Vana moksha: 30M (use 25M for safety)\n * - Ethereum mainnet: 30M (use 25M for safety)\n * - Arbitrum: 32M (use 25M for safety)\n */\n maxGasPerBatch?: bigint;\n\n /**\n * Maximum calldata size per batch in bytes. Defaults to 100KB.\n *\n * @remarks\n * This is particularly important for L2 chains where calldata is expensive.\n * Some RPC providers also have limits on request size.\n */\n maxCalldataBytes?: number;\n\n /**\n * How often to checkpoint gas estimates. Defaults to every 32 calls or 8KB.\n *\n * @remarks\n * More frequent checkpoints give more accurate batching but require more\n * RPC calls for gas estimation. The default balances accuracy vs performance.\n */\n checkpointFrequency?: {\n /** Checkpoint after this many calls */\n calls: number;\n /** Checkpoint after this many bytes of calldata */\n bytes: number;\n };\n\n /**\n * Whether to allow partial batch failures. Defaults to false.\n *\n * @remarks\n * When true, individual call failures won't fail the entire batch.\n * This matches viem's multicall behavior with allowFailure option.\n */\n allowFailure?: boolean;\n\n /**\n * Optional multicall3 contract address override.\n *\n * @remarks\n * By default, uses the standard multicall3 address deployed on most chains:\n * 0xcA11bde05977b3631167028862bE2a173976CA11\n */\n multicallAddress?: Address;\n\n /**\n * Optional callback for tracking batching progress.\n *\n * @remarks\n * Useful for showing progress in UI or debugging batch performance.\n */\n onProgress?: (completed: number, total: number) => void;\n}\n\n/**\n * Internal configuration with defaults applied\n */\ninterface NormalizedOptions {\n maxGasPerBatch: bigint;\n maxCalldataBytes: number;\n checkpointFrequency: {\n calls: number;\n bytes: number;\n };\n allowFailure: boolean;\n multicallAddress: Address;\n onProgress?: (completed: number, total: number) => void;\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULT_OPTIONS: Omit<NormalizedOptions, \"multicallAddress\"> = {\n maxGasPerBatch: 10_000_000n, // 10M gas - conservative default\n maxCalldataBytes: 100_000, // 100KB - works with most RPC providers\n checkpointFrequency: {\n calls: 32,\n bytes: 8192, // 8KB\n },\n allowFailure: false,\n};\n\n/**\n * A gas-aware multicall function that automatically batches calls to stay within limits.\n *\n * @remarks\n * This function extends viem's multicall with intelligent batching based on:\n * - Actual gas costs (via periodic estimateGas calls)\n * - Calldata size limits\n * - Chain-specific constraints\n *\n * It uses a greedy algorithm with periodic checkpoints to efficiently determine\n * optimal batch sizes without making excessive RPC calls.\n *\n * @param client - The viem public client to use for RPC calls\n * @param parameters - The multicall parameters (same as viem's multicall)\n * @param options - Optional configuration for gas-aware batching\n * @returns The aggregated results from all batches\n *\n * @example\n * ```typescript\n * // Basic usage - drop-in replacement for viem's multicall\n * const results = await gasAwareMulticall(publicClient, {\n * contracts: [\n * { address: '0x...', abi: erc20Abi, functionName: 'balanceOf', args: [address1] },\n * { address: '0x...', abi: erc20Abi, functionName: 'balanceOf', args: [address2] },\n * // ... hundreds more calls\n * ]\n * });\n *\n * // With custom limits for a specific chain\n * const results = await gasAwareMulticall(publicClient, {\n * contracts: calls,\n * }, {\n * maxGasPerBatch: 25_000_000n, // 25M for mainnet\n * maxCalldataBytes: 128_000, // 128KB\n * onProgress: (done, total) => console.log(`Progress: ${done}/${total}`)\n * });\n * ```\n */\nexport async function gasAwareMulticall<\n TContracts extends readonly ContractFunctionConfig[],\n TAllowFailure extends boolean = false,\n>(\n client: PublicClient,\n parameters: MulticallParameters<TContracts, TAllowFailure>,\n options: GasAwareMulticallOptions = {},\n): Promise<MulticallReturnType<TContracts, TAllowFailure>> {\n // Get the chain-specific Multicall3 address\n const chainId = await client.getChainId();\n const multicall3Address =\n options.multicallAddress ??\n getUtilityAddress(chainId as VanaChainId, \"Multicall3\");\n\n // Normalize options with defaults\n const opts: NormalizedOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n multicallAddress: multicall3Address,\n checkpointFrequency: {\n ...DEFAULT_OPTIONS.checkpointFrequency,\n ...options.checkpointFrequency,\n },\n };\n\n // Override allowFailure if specified in parameters\n if (parameters.allowFailure !== undefined) {\n opts.allowFailure = parameters.allowFailure;\n }\n\n const { contracts } = parameters;\n if (!contracts || contracts.length === 0) {\n // TODO(TYPES): Empty array needs to match complex generic return type.\n // Future improvement: Use conditional types to properly type empty results\n // based on TAllowFailure parameter. Consider creating utility type helper.\n return [] as unknown as MulticallReturnType<TContracts, TAllowFailure>;\n }\n\n // Execute batching algorithm\n const batches = await createBatches(\n client,\n contracts as readonly ContractFunctionConfig[],\n opts,\n );\n\n // Execute all batches in parallel\n const batchResults = await Promise.all(\n batches.map((batch, index) => {\n // Report progress if callback provided\n if (opts.onProgress && index > 0) {\n const completed = batches\n .slice(0, index)\n .reduce((sum, b) => sum + b.length, 0);\n opts.onProgress(completed, contracts.length);\n }\n\n // Execute batch using viem's multicall\n return client.multicall({\n ...parameters,\n contracts: batch as typeof contracts,\n multicallAddress: opts.multicallAddress,\n allowFailure: opts.allowFailure,\n });\n }),\n );\n\n // Report final progress\n if (opts.onProgress) {\n opts.onProgress(contracts.length, contracts.length);\n }\n\n // Flatten results\n return batchResults.flat() as MulticallReturnType<TContracts, TAllowFailure>;\n}\n\n/**\n * Creates optimally-sized batches using greedy algorithm with checkpoints.\n *\n * @param client - The viem public client for making RPC calls\n * @param contracts - Array of contract function configurations to batch\n * @param options - Normalized batching options with limits and settings\n * @returns Array of optimally-sized contract function configuration batches\n */\nasync function createBatches(\n client: PublicClient,\n contracts: readonly ContractFunctionConfig[],\n options: NormalizedOptions,\n): Promise<ContractFunctionConfig[][]> {\n const batches: ContractFunctionConfig[][] = [];\n let currentBatch: ContractFunctionConfig[] = [];\n let currentBytes = 0;\n let lastCheckpointIndex = 0;\n let lastCheckpointBytes = 0;\n let lastEstimatedGas = 0n;\n\n for (let i = 0; i < contracts.length; i++) {\n const contract = contracts[i];\n\n // Calculate encoded size for this call\n const encoded = encodeContractCall(contract);\n const callBytes = size(encoded);\n\n // Check if we need a gas checkpoint\n const callsSinceCheckpoint = i - lastCheckpointIndex;\n const bytesSinceCheckpoint = currentBytes - lastCheckpointBytes;\n\n const needsCheckpoint =\n callsSinceCheckpoint >= options.checkpointFrequency.calls ||\n bytesSinceCheckpoint >= options.checkpointFrequency.bytes;\n\n // Perform checkpoint if needed\n if (needsCheckpoint && currentBatch.length > 0) {\n try {\n lastEstimatedGas = await estimateBatchGas(\n client,\n currentBatch,\n options.multicallAddress,\n );\n lastCheckpointIndex = i;\n lastCheckpointBytes = currentBytes;\n } catch (error) {\n // If estimation fails, finalize current batch to be safe\n if (currentBatch.length > 1) {\n // Try with half the batch\n const halfBatch = currentBatch.slice(\n 0,\n Math.floor(currentBatch.length / 2),\n );\n batches.push(halfBatch);\n currentBatch = currentBatch.slice(halfBatch.length);\n currentBytes = calculateBatchSize(currentBatch);\n lastCheckpointIndex = i;\n lastCheckpointBytes = currentBytes;\n lastEstimatedGas = 0n;\n } else {\n // Single call failed, skip it or throw based on allowFailure\n if (!options.allowFailure) {\n throw new Error(\n `Gas estimation failed for call ${i}: ${String(error)}`,\n );\n }\n currentBatch = [];\n currentBytes = 0;\n continue;\n }\n }\n }\n\n // Check if adding this call would exceed limits\n const wouldExceedCalldata =\n currentBytes + callBytes > options.maxCalldataBytes;\n const wouldExceedGas =\n lastEstimatedGas > 0n &&\n estimateNextGas(lastEstimatedGas, callsSinceCheckpoint + 1) >\n options.maxGasPerBatch;\n\n // If we would exceed limits, finalize current batch\n if ((wouldExceedCalldata || wouldExceedGas) && currentBatch.length > 0) {\n batches.push(currentBatch);\n currentBatch = [];\n currentBytes = 0;\n lastCheckpointIndex = i;\n lastCheckpointBytes = 0;\n lastEstimatedGas = 0n;\n }\n\n // Add call to current batch\n currentBatch.push(contract);\n currentBytes += callBytes;\n }\n\n // Add final batch if not empty\n if (currentBatch.length > 0) {\n batches.push(currentBatch);\n }\n\n return batches;\n}\n\n/**\n * Encodes a contract call to measure its calldata size.\n *\n * @param contract - The contract function configuration to encode\n * @returns Hex-encoded function data\n */\nfunction encodeContractCall(contract: ContractFunctionConfig): Hex {\n const { abi, functionName, args } = contract;\n\n return encodeFunctionData({\n abi,\n functionName,\n args,\n } as EncodeFunctionDataParameters);\n}\n\n/**\n * Calculates total encoded size of a batch.\n *\n * @param batch - Array of contract function configurations to measure\n * @returns Total size in bytes of all encoded calls in the batch\n */\nfunction calculateBatchSize(batch: ContractFunctionConfig[]): number {\n return batch.reduce((total, contract) => {\n const encoded = encodeContractCall(contract);\n return total + size(encoded);\n }, 0);\n}\n\n/**\n * Estimates gas for a batch of calls via multicall3.\n *\n * @param client - The viem public client for gas estimation\n * @param batch - Array of contract calls to estimate gas for\n * @param multicallAddress - The multicall3 contract address to use\n * @returns Estimated gas cost for executing the batch\n */\nasync function estimateBatchGas(\n client: PublicClient,\n batch: ContractFunctionConfig[],\n multicallAddress: Address,\n): Promise<bigint> {\n // Encode batch as multicall3 aggregate3 call\n const calls = batch.map((contract) => ({\n target: contract.address,\n allowFailure: false,\n callData: encodeContractCall(contract),\n }));\n\n // Estimate gas for the multicall\n const gas = await client.estimateGas({\n to: multicallAddress,\n data: encodeFunctionData({\n abi: multicall3Abi,\n functionName: \"aggregate3\",\n args: [calls],\n }),\n });\n\n return gas;\n}\n\n/**\n * Extrapolates gas usage for calls added since last checkpoint.\n *\n * @remarks\n * Uses a conservative 1.1x multiplier for safety to account for gas usage variations.\n *\n * @param lastGas - The gas estimate from the last checkpoint\n * @param callsSinceCheckpoint - Number of calls added since the checkpoint\n * @returns Extrapolated gas estimate with safety margin\n */\nfunction estimateNextGas(\n lastGas: bigint,\n callsSinceCheckpoint: number,\n): bigint {\n if (callsSinceCheckpoint === 0) return lastGas;\n\n // Assume linear scaling with safety factor\n const avgGasPerCall = lastGas / BigInt(Math.max(1, callsSinceCheckpoint - 1));\n const estimatedGas = lastGas + avgGasPerCall;\n\n // Apply 10% safety margin\n return (estimatedGas * 110n) / 100n;\n}\n\n/**\n * Minimal multicall3 ABI for gas estimation\n */\nconst multicall3Abi = [\n {\n name: \"aggregate3\",\n type: \"function\",\n stateMutability: \"payable\",\n inputs: [\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"allowFailure\", type: \"bool\" },\n { name: \"callData\", type: \"bytes\" },\n ],\n },\n ],\n outputs: [\n {\n name: \"returnData\",\n type: \"tuple[]\",\n components: [\n { name: \"success\", type: \"bool\" },\n { name: \"returnData\", type: \"bytes\" },\n ],\n },\n ],\n },\n] as const;\n\n/**\n * Utility function to analyze calls and predict optimal batch configuration\n *\n * @remarks\n * This function helps determine the best configuration for a specific set of calls\n * by analyzing their characteristics. Useful for optimizing repeated operations.\n *\n * @param contracts - The calls to analyze\n * @returns Suggested configuration based on call analysis\n */\nexport function analyzeCallsForOptimalConfig(\n contracts: readonly ContractFunctionConfig[],\n): Pick<GasAwareMulticallOptions, \"checkpointFrequency\" | \"maxCalldataBytes\"> {\n // Calculate average call size\n const totalBytes = contracts.reduce((sum, contract) => {\n const encoded = encodeContractCall(contract);\n return sum + size(encoded);\n }, 0);\n\n const avgBytesPerCall = totalBytes / contracts.length;\n\n // Suggest checkpoint frequency based on call density\n const checkpointFrequency = {\n calls: avgBytesPerCall > 500 ? 16 : 32, // More frequent for large calls\n bytes: avgBytesPerCall > 500 ? 4096 : 8192,\n };\n\n // Suggest calldata limit based on total size\n // For 1000 calls with small arrays, totalBytes will be much less than 500KB,\n // so use number of contracts as additional signal\n const maxCalldataBytes =\n totalBytes > 50_000 || contracts.length > 500 ? 128_000 : 100_000;\n\n return {\n checkpointFrequency,\n maxCalldataBytes,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/parseTransactionPojo.ts"],"sourcesContent":["/**\n * Transaction parsing with POJO support and NO heuristics.\n * \n * @remarks\n * This is the new POJO-based parser that works with TransactionResult objects.\n * Principle: Explicit over implicit, guarantees over guesses.\n */\n\nimport { decodeEventLog, type TransactionReceipt } from 'viem';\nimport type { TransactionResult } from '../types/operations';\nimport type { TypedTransactionResult, Contract, Fn, ExpectedEvents } from '../generated/event-types';\nimport { EVENT_REGISTRY, TOPIC_TO_ABIS } from '../generated/eventRegistry';\n\n/**\n * Parses a transaction using TransactionResult POJO with ZERO heuristics.\n * \n * @remarks\n * - Uses function-scoped event registry for O(1) lookups\n * - Only expects events explicitly mapped for this contract.function\n * - Returns typed events matching the exact TypedTransactionResult interface\n * \n * @param transactionResult - The TransactionResult POJO with context\n * @param transactionResult.hash - Transaction hash\n * @param transactionResult.from - Transaction sender address\n * @param transactionResult.contract - Contract name\n * @param transactionResult.fn - Function name\n * @param transactionResult.chainId - Optional chain ID\n * @param transactionResult.value - Optional transaction value\n * @param transactionResult.nonce - Optional nonce\n * @param transactionResult.to - Optional recipient address\n * @param receipt - The transaction receipt from the blockchain\n * @returns Typed transaction result with parsed events\n */\nexport function parseTransaction<C extends Contract, F extends Fn<C>>(\n transactionResult: TransactionResult<C, F>,\n receipt: TransactionReceipt\n): TypedTransactionResult<C, F> {\n const { contract: contractName, fn: functionName } = transactionResult;\n \n // Look up expected events from the function-specific registry\n const registryKey = `${contractName}.${functionName}`;\n const registry = EVENT_REGISTRY[registryKey as keyof typeof EVENT_REGISTRY];\n \n // Initialize the expected events object with proper types\n const expectedEvents: Record<string, unknown> = {};\n const allEvents: Array<{\n contractAddress: string;\n eventName: string;\n args: Record<string, unknown>;\n logIndex: number;\n }> = [];\n \n let hasExpectedEvents = false;\n \n if (receipt.logs) {\n // Parse logs using the function-scoped registry\n for (const log of receipt.logs) {\n if (!log.topics || log.topics.length === 0) {\n // Skip malformed logs\n continue;\n }\n \n const eventTopic = log.topics[0] as `0x${string}`;\n \n // Try to decode using TOPIC_TO_ABIS for O(1) lookup\n const abiCandidates = TOPIC_TO_ABIS.get(eventTopic);\n \n if (abiCandidates && abiCandidates.length > 0) {\n // Try each ABI variant (handles collisions)\n for (const abiEvent of abiCandidates) {\n try {\n const decoded = decodeEventLog({\n abi: [abiEvent],\n data: log.data,\n topics: log.topics as [`0x${string}`, ...`0x${string}`[]],\n });\n \n // Add to allEvents\n allEvents.push({\n contractAddress: log.address || '',\n eventName: decoded.eventName,\n args: decoded.args as Record<string, unknown>,\n logIndex: log.logIndex ?? 0,\n });\n \n // If this event is expected for this function, add to expectedEvents\n if (registry && registry.eventNames.includes(decoded.eventName)) {\n expectedEvents[decoded.eventName] = decoded.args;\n hasExpectedEvents = true;\n }\n \n break; // Successfully decoded, don't try other variants\n } catch {\n // Try next ABI variant\n continue;\n }\n }\n } else {\n // Event not decodable, add as unknown\n allEvents.push({\n contractAddress: log.address || '',\n eventName: 'Unknown',\n args: { topic0: eventTopic, data: log.data },\n logIndex: log.logIndex ?? 0,\n });\n }\n }\n }\n \n // Return a properly typed TypedTransactionResult\n return {\n hash: transactionResult.hash,\n from: transactionResult.from,\n contract: contractName as C,\n fn: functionName as F,\n expectedEvents: expectedEvents as ExpectedEvents<C, F>,\n allEvents,\n hasExpectedEvents,\n };\n}"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,kBAAwD;AAGxD,2BAA8C;AAsBvC,SAAS,iBACd,mBACA,SAC8B;AAC9B,QAAM,EAAE,UAAU,cAAc,IAAI,aAAa,IAAI;AAGrD,QAAM,cAAc,GAAG,YAAY,IAAI,YAAY;AACnD,QAAM,WAAW,oCAAe,WAA0C;AAG1E,QAAM,iBAA0C,CAAC;AACjD,QAAM,YAKD,CAAC;AAEN,MAAI,oBAAoB;AAExB,MAAI,QAAQ,MAAM;AAEhB,eAAW,OAAO,QAAQ,MAAM;AAC9B,UAAI,CAAC,IAAI,UAAU,IAAI,OAAO,WAAW,GAAG;AAE1C;AAAA,MACF;AAEA,YAAM,aAAa,IAAI,OAAO,CAAC;AAG/B,YAAM,gBAAgB,mCAAc,IAAI,UAAU;AAElD,UAAI,iBAAiB,cAAc,SAAS,GAAG;AAE7C,mBAAW,YAAY,eAAe;AACpC,cAAI;AACF,kBAAM,cAAU,4BAAe;AAAA,cAC7B,KAAK,CAAC,QAAQ;AAAA,cACd,MAAM,IAAI;AAAA,cACV,QAAQ,IAAI;AAAA,YACd,CAAC;AAGD,sBAAU,KAAK;AAAA,cACb,iBAAiB,IAAI,WAAW;AAAA,cAChC,WAAW,QAAQ;AAAA,cACnB,MAAM,QAAQ;AAAA,cACd,UAAU,IAAI,YAAY;AAAA,YAC5B,CAAC;AAGD,gBAAI,YAAY,SAAS,WAAW,SAAS,QAAQ,SAAS,GAAG;AAC/D,6BAAe,QAAQ,SAAS,IAAI,QAAQ;AAC5C,kCAAoB;AAAA,YACtB;AAEA;AAAA,UACF,QAAQ;AAEN;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,kBAAU,KAAK;AAAA,UACb,iBAAiB,IAAI,WAAW;AAAA,UAChC,WAAW;AAAA,UACX,MAAM,EAAE,QAAQ,YAAY,MAAM,IAAI,KAAK;AAAA,UAC3C,UAAU,IAAI,YAAY;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,MAAM,kBAAkB;AAAA,IACxB,MAAM,kBAAkB;AAAA,IACxB,UAAU;AAAA,IACV,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/parseTransactionPojo.ts"],"sourcesContent":["/**\n * Transaction parsing with POJO support and NO heuristics.\n *\n * @remarks\n * This is the new POJO-based parser that works with TransactionResult objects.\n * Principle: Explicit over implicit, guarantees over guesses.\n */\n\nimport { decodeEventLog, type TransactionReceipt } from \"viem\";\nimport type { TransactionResult } from \"../types/operations\";\nimport type {\n TypedTransactionResult,\n Contract,\n Fn,\n ExpectedEvents,\n} from \"../generated/event-types\";\nimport { EVENT_REGISTRY, TOPIC_TO_ABIS } from \"../generated/eventRegistry\";\n\n/**\n * Parses a transaction using TransactionResult POJO with ZERO heuristics.\n *\n * @remarks\n * - Uses function-scoped event registry for O(1) lookups\n * - Only expects events explicitly mapped for this contract.function\n * - Returns typed events matching the exact TypedTransactionResult interface\n *\n * @param transactionResult - The TransactionResult POJO with context\n * @param transactionResult.hash - Transaction hash\n * @param transactionResult.from - Transaction sender address\n * @param transactionResult.contract - Contract name\n * @param transactionResult.fn - Function name\n * @param transactionResult.chainId - Optional chain ID\n * @param transactionResult.value - Optional transaction value\n * @param transactionResult.nonce - Optional nonce\n * @param transactionResult.to - Optional recipient address\n * @param receipt - The transaction receipt from the blockchain\n * @returns Typed transaction result with parsed events\n */\nexport function parseTransaction<C extends Contract, F extends Fn<C>>(\n transactionResult: TransactionResult<C, F>,\n receipt: TransactionReceipt,\n): TypedTransactionResult<C, F> {\n const { contract: contractName, fn: functionName } = transactionResult;\n\n // Look up expected events from the function-specific registry\n const registryKey = `${contractName}.${functionName}`;\n const registry = EVENT_REGISTRY[registryKey];\n\n // Initialize the expected events object with proper types\n const expectedEvents: Record<string, unknown> = {};\n const allEvents: Array<{\n contractAddress: string;\n eventName: string;\n args: Record<string, unknown>;\n logIndex: number;\n }> = [];\n\n let hasExpectedEvents = false;\n\n if (receipt.logs) {\n // Parse logs using the function-scoped registry\n for (const log of receipt.logs) {\n if (!log.topics || log.topics.length === 0) {\n // Skip malformed logs\n continue;\n }\n\n const eventTopic = log.topics[0] as `0x${string}`;\n\n // Try to decode using TOPIC_TO_ABIS for O(1) lookup\n const abiCandidates = TOPIC_TO_ABIS.get(eventTopic);\n\n if (abiCandidates && abiCandidates.length > 0) {\n // Try each ABI variant (handles collisions)\n for (const abiEvent of abiCandidates) {\n try {\n const decoded = decodeEventLog({\n abi: [abiEvent],\n data: log.data,\n topics: log.topics as [`0x${string}`, ...`0x${string}`[]],\n });\n\n // Add to allEvents\n allEvents.push({\n contractAddress: log.address || \"\",\n eventName: decoded.eventName,\n args: decoded.args as Record<string, unknown>,\n logIndex: log.logIndex ?? 0,\n });\n\n // If this event is expected for this function, add to expectedEvents\n if (registry && registry.eventNames.includes(decoded.eventName)) {\n expectedEvents[decoded.eventName] = decoded.args;\n hasExpectedEvents = true;\n }\n\n break; // Successfully decoded, don't try other variants\n } catch {\n // Try next ABI variant\n continue;\n }\n }\n } else {\n // Event not decodable, add as unknown\n allEvents.push({\n contractAddress: log.address || \"\",\n eventName: \"Unknown\",\n args: { topic0: eventTopic, data: log.data },\n logIndex: log.logIndex ?? 0,\n });\n }\n }\n }\n\n // Return a properly typed TypedTransactionResult\n return {\n hash: transactionResult.hash,\n from: transactionResult.from,\n contract: contractName,\n fn: functionName,\n expectedEvents: expectedEvents as ExpectedEvents<C, F>,\n allEvents,\n hasExpectedEvents,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,kBAAwD;AAQxD,2BAA8C;AAsBvC,SAAS,iBACd,mBACA,SAC8B;AAC9B,QAAM,EAAE,UAAU,cAAc,IAAI,aAAa,IAAI;AAGrD,QAAM,cAAc,GAAG,YAAY,IAAI,YAAY;AACnD,QAAM,WAAW,oCAAe,WAAW;AAG3C,QAAM,iBAA0C,CAAC;AACjD,QAAM,YAKD,CAAC;AAEN,MAAI,oBAAoB;AAExB,MAAI,QAAQ,MAAM;AAEhB,eAAW,OAAO,QAAQ,MAAM;AAC9B,UAAI,CAAC,IAAI,UAAU,IAAI,OAAO,WAAW,GAAG;AAE1C;AAAA,MACF;AAEA,YAAM,aAAa,IAAI,OAAO,CAAC;AAG/B,YAAM,gBAAgB,mCAAc,IAAI,UAAU;AAElD,UAAI,iBAAiB,cAAc,SAAS,GAAG;AAE7C,mBAAW,YAAY,eAAe;AACpC,cAAI;AACF,kBAAM,cAAU,4BAAe;AAAA,cAC7B,KAAK,CAAC,QAAQ;AAAA,cACd,MAAM,IAAI;AAAA,cACV,QAAQ,IAAI;AAAA,YACd,CAAC;AAGD,sBAAU,KAAK;AAAA,cACb,iBAAiB,IAAI,WAAW;AAAA,cAChC,WAAW,QAAQ;AAAA,cACnB,MAAM,QAAQ;AAAA,cACd,UAAU,IAAI,YAAY;AAAA,YAC5B,CAAC;AAGD,gBAAI,YAAY,SAAS,WAAW,SAAS,QAAQ,SAAS,GAAG;AAC/D,6BAAe,QAAQ,SAAS,IAAI,QAAQ;AAC5C,kCAAoB;AAAA,YACtB;AAEA;AAAA,UACF,QAAQ;AAEN;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,kBAAU,KAAK;AAAA,UACb,iBAAiB,IAAI,WAAW;AAAA,UAChC,WAAW;AAAA,UACX,MAAM,EAAE,QAAQ,YAAY,MAAM,IAAI,KAAK;AAAA,UAC3C,UAAU,IAAI,YAAY;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,MAAM,kBAAkB;AAAA,IACxB,MAAM,kBAAkB;AAAA,IACxB,UAAU;AAAA,IACV,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
@@ -1,9 +1,3 @@
1
- import { TransactionReceipt } from 'viem';
2
- import { TransactionResult } from '../types/operations.js';
3
- import { Contract, Fn, TypedTransactionResult } from '../generated/event-types.js';
4
- import '../generated/server/server-exports.js';
5
- import '../generated/server/server.js';
6
-
7
1
  /**
8
2
  * Transaction parsing with POJO support and NO heuristics.
9
3
  *
@@ -11,7 +5,9 @@ import '../generated/server/server.js';
11
5
  * This is the new POJO-based parser that works with TransactionResult objects.
12
6
  * Principle: Explicit over implicit, guarantees over guesses.
13
7
  */
14
-
8
+ import { type TransactionReceipt } from "viem";
9
+ import type { TransactionResult } from "../types/operations";
10
+ import type { TypedTransactionResult, Contract, Fn } from "../generated/event-types";
15
11
  /**
16
12
  * Parses a transaction using TransactionResult POJO with ZERO heuristics.
17
13
  *
@@ -32,6 +28,4 @@ import '../generated/server/server.js';
32
28
  * @param receipt - The transaction receipt from the blockchain
33
29
  * @returns Typed transaction result with parsed events
34
30
  */
35
- declare function parseTransaction<C extends Contract, F extends Fn<C>>(transactionResult: TransactionResult<C, F>, receipt: TransactionReceipt): TypedTransactionResult<C, F>;
36
-
37
- export { parseTransaction };
31
+ export declare function parseTransaction<C extends Contract, F extends Fn<C>>(transactionResult: TransactionResult<C, F>, receipt: TransactionReceipt): TypedTransactionResult<C, F>;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/parseTransactionPojo.ts"],"sourcesContent":["/**\n * Transaction parsing with POJO support and NO heuristics.\n * \n * @remarks\n * This is the new POJO-based parser that works with TransactionResult objects.\n * Principle: Explicit over implicit, guarantees over guesses.\n */\n\nimport { decodeEventLog, type TransactionReceipt } from 'viem';\nimport type { TransactionResult } from '../types/operations';\nimport type { TypedTransactionResult, Contract, Fn, ExpectedEvents } from '../generated/event-types';\nimport { EVENT_REGISTRY, TOPIC_TO_ABIS } from '../generated/eventRegistry';\n\n/**\n * Parses a transaction using TransactionResult POJO with ZERO heuristics.\n * \n * @remarks\n * - Uses function-scoped event registry for O(1) lookups\n * - Only expects events explicitly mapped for this contract.function\n * - Returns typed events matching the exact TypedTransactionResult interface\n * \n * @param transactionResult - The TransactionResult POJO with context\n * @param transactionResult.hash - Transaction hash\n * @param transactionResult.from - Transaction sender address\n * @param transactionResult.contract - Contract name\n * @param transactionResult.fn - Function name\n * @param transactionResult.chainId - Optional chain ID\n * @param transactionResult.value - Optional transaction value\n * @param transactionResult.nonce - Optional nonce\n * @param transactionResult.to - Optional recipient address\n * @param receipt - The transaction receipt from the blockchain\n * @returns Typed transaction result with parsed events\n */\nexport function parseTransaction<C extends Contract, F extends Fn<C>>(\n transactionResult: TransactionResult<C, F>,\n receipt: TransactionReceipt\n): TypedTransactionResult<C, F> {\n const { contract: contractName, fn: functionName } = transactionResult;\n \n // Look up expected events from the function-specific registry\n const registryKey = `${contractName}.${functionName}`;\n const registry = EVENT_REGISTRY[registryKey as keyof typeof EVENT_REGISTRY];\n \n // Initialize the expected events object with proper types\n const expectedEvents: Record<string, unknown> = {};\n const allEvents: Array<{\n contractAddress: string;\n eventName: string;\n args: Record<string, unknown>;\n logIndex: number;\n }> = [];\n \n let hasExpectedEvents = false;\n \n if (receipt.logs) {\n // Parse logs using the function-scoped registry\n for (const log of receipt.logs) {\n if (!log.topics || log.topics.length === 0) {\n // Skip malformed logs\n continue;\n }\n \n const eventTopic = log.topics[0] as `0x${string}`;\n \n // Try to decode using TOPIC_TO_ABIS for O(1) lookup\n const abiCandidates = TOPIC_TO_ABIS.get(eventTopic);\n \n if (abiCandidates && abiCandidates.length > 0) {\n // Try each ABI variant (handles collisions)\n for (const abiEvent of abiCandidates) {\n try {\n const decoded = decodeEventLog({\n abi: [abiEvent],\n data: log.data,\n topics: log.topics as [`0x${string}`, ...`0x${string}`[]],\n });\n \n // Add to allEvents\n allEvents.push({\n contractAddress: log.address || '',\n eventName: decoded.eventName,\n args: decoded.args as Record<string, unknown>,\n logIndex: log.logIndex ?? 0,\n });\n \n // If this event is expected for this function, add to expectedEvents\n if (registry && registry.eventNames.includes(decoded.eventName)) {\n expectedEvents[decoded.eventName] = decoded.args;\n hasExpectedEvents = true;\n }\n \n break; // Successfully decoded, don't try other variants\n } catch {\n // Try next ABI variant\n continue;\n }\n }\n } else {\n // Event not decodable, add as unknown\n allEvents.push({\n contractAddress: log.address || '',\n eventName: 'Unknown',\n args: { topic0: eventTopic, data: log.data },\n logIndex: log.logIndex ?? 0,\n });\n }\n }\n }\n \n // Return a properly typed TypedTransactionResult\n return {\n hash: transactionResult.hash,\n from: transactionResult.from,\n contract: contractName as C,\n fn: functionName as F,\n expectedEvents: expectedEvents as ExpectedEvents<C, F>,\n allEvents,\n hasExpectedEvents,\n };\n}"],"mappings":"AAQA,SAAS,sBAA+C;AAGxD,SAAS,gBAAgB,qBAAqB;AAsBvC,SAAS,iBACd,mBACA,SAC8B;AAC9B,QAAM,EAAE,UAAU,cAAc,IAAI,aAAa,IAAI;AAGrD,QAAM,cAAc,GAAG,YAAY,IAAI,YAAY;AACnD,QAAM,WAAW,eAAe,WAA0C;AAG1E,QAAM,iBAA0C,CAAC;AACjD,QAAM,YAKD,CAAC;AAEN,MAAI,oBAAoB;AAExB,MAAI,QAAQ,MAAM;AAEhB,eAAW,OAAO,QAAQ,MAAM;AAC9B,UAAI,CAAC,IAAI,UAAU,IAAI,OAAO,WAAW,GAAG;AAE1C;AAAA,MACF;AAEA,YAAM,aAAa,IAAI,OAAO,CAAC;AAG/B,YAAM,gBAAgB,cAAc,IAAI,UAAU;AAElD,UAAI,iBAAiB,cAAc,SAAS,GAAG;AAE7C,mBAAW,YAAY,eAAe;AACpC,cAAI;AACF,kBAAM,UAAU,eAAe;AAAA,cAC7B,KAAK,CAAC,QAAQ;AAAA,cACd,MAAM,IAAI;AAAA,cACV,QAAQ,IAAI;AAAA,YACd,CAAC;AAGD,sBAAU,KAAK;AAAA,cACb,iBAAiB,IAAI,WAAW;AAAA,cAChC,WAAW,QAAQ;AAAA,cACnB,MAAM,QAAQ;AAAA,cACd,UAAU,IAAI,YAAY;AAAA,YAC5B,CAAC;AAGD,gBAAI,YAAY,SAAS,WAAW,SAAS,QAAQ,SAAS,GAAG;AAC/D,6BAAe,QAAQ,SAAS,IAAI,QAAQ;AAC5C,kCAAoB;AAAA,YACtB;AAEA;AAAA,UACF,QAAQ;AAEN;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,kBAAU,KAAK;AAAA,UACb,iBAAiB,IAAI,WAAW;AAAA,UAChC,WAAW;AAAA,UACX,MAAM,EAAE,QAAQ,YAAY,MAAM,IAAI,KAAK;AAAA,UAC3C,UAAU,IAAI,YAAY;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,MAAM,kBAAkB;AAAA,IACxB,MAAM,kBAAkB;AAAA,IACxB,UAAU;AAAA,IACV,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/parseTransactionPojo.ts"],"sourcesContent":["/**\n * Transaction parsing with POJO support and NO heuristics.\n *\n * @remarks\n * This is the new POJO-based parser that works with TransactionResult objects.\n * Principle: Explicit over implicit, guarantees over guesses.\n */\n\nimport { decodeEventLog, type TransactionReceipt } from \"viem\";\nimport type { TransactionResult } from \"../types/operations\";\nimport type {\n TypedTransactionResult,\n Contract,\n Fn,\n ExpectedEvents,\n} from \"../generated/event-types\";\nimport { EVENT_REGISTRY, TOPIC_TO_ABIS } from \"../generated/eventRegistry\";\n\n/**\n * Parses a transaction using TransactionResult POJO with ZERO heuristics.\n *\n * @remarks\n * - Uses function-scoped event registry for O(1) lookups\n * - Only expects events explicitly mapped for this contract.function\n * - Returns typed events matching the exact TypedTransactionResult interface\n *\n * @param transactionResult - The TransactionResult POJO with context\n * @param transactionResult.hash - Transaction hash\n * @param transactionResult.from - Transaction sender address\n * @param transactionResult.contract - Contract name\n * @param transactionResult.fn - Function name\n * @param transactionResult.chainId - Optional chain ID\n * @param transactionResult.value - Optional transaction value\n * @param transactionResult.nonce - Optional nonce\n * @param transactionResult.to - Optional recipient address\n * @param receipt - The transaction receipt from the blockchain\n * @returns Typed transaction result with parsed events\n */\nexport function parseTransaction<C extends Contract, F extends Fn<C>>(\n transactionResult: TransactionResult<C, F>,\n receipt: TransactionReceipt,\n): TypedTransactionResult<C, F> {\n const { contract: contractName, fn: functionName } = transactionResult;\n\n // Look up expected events from the function-specific registry\n const registryKey = `${contractName}.${functionName}`;\n const registry = EVENT_REGISTRY[registryKey];\n\n // Initialize the expected events object with proper types\n const expectedEvents: Record<string, unknown> = {};\n const allEvents: Array<{\n contractAddress: string;\n eventName: string;\n args: Record<string, unknown>;\n logIndex: number;\n }> = [];\n\n let hasExpectedEvents = false;\n\n if (receipt.logs) {\n // Parse logs using the function-scoped registry\n for (const log of receipt.logs) {\n if (!log.topics || log.topics.length === 0) {\n // Skip malformed logs\n continue;\n }\n\n const eventTopic = log.topics[0] as `0x${string}`;\n\n // Try to decode using TOPIC_TO_ABIS for O(1) lookup\n const abiCandidates = TOPIC_TO_ABIS.get(eventTopic);\n\n if (abiCandidates && abiCandidates.length > 0) {\n // Try each ABI variant (handles collisions)\n for (const abiEvent of abiCandidates) {\n try {\n const decoded = decodeEventLog({\n abi: [abiEvent],\n data: log.data,\n topics: log.topics as [`0x${string}`, ...`0x${string}`[]],\n });\n\n // Add to allEvents\n allEvents.push({\n contractAddress: log.address || \"\",\n eventName: decoded.eventName,\n args: decoded.args as Record<string, unknown>,\n logIndex: log.logIndex ?? 0,\n });\n\n // If this event is expected for this function, add to expectedEvents\n if (registry && registry.eventNames.includes(decoded.eventName)) {\n expectedEvents[decoded.eventName] = decoded.args;\n hasExpectedEvents = true;\n }\n\n break; // Successfully decoded, don't try other variants\n } catch {\n // Try next ABI variant\n continue;\n }\n }\n } else {\n // Event not decodable, add as unknown\n allEvents.push({\n contractAddress: log.address || \"\",\n eventName: \"Unknown\",\n args: { topic0: eventTopic, data: log.data },\n logIndex: log.logIndex ?? 0,\n });\n }\n }\n }\n\n // Return a properly typed TypedTransactionResult\n return {\n hash: transactionResult.hash,\n from: transactionResult.from,\n contract: contractName,\n fn: functionName,\n expectedEvents: expectedEvents as ExpectedEvents<C, F>,\n allEvents,\n hasExpectedEvents,\n };\n}\n"],"mappings":"AAQA,SAAS,sBAA+C;AAQxD,SAAS,gBAAgB,qBAAqB;AAsBvC,SAAS,iBACd,mBACA,SAC8B;AAC9B,QAAM,EAAE,UAAU,cAAc,IAAI,aAAa,IAAI;AAGrD,QAAM,cAAc,GAAG,YAAY,IAAI,YAAY;AACnD,QAAM,WAAW,eAAe,WAAW;AAG3C,QAAM,iBAA0C,CAAC;AACjD,QAAM,YAKD,CAAC;AAEN,MAAI,oBAAoB;AAExB,MAAI,QAAQ,MAAM;AAEhB,eAAW,OAAO,QAAQ,MAAM;AAC9B,UAAI,CAAC,IAAI,UAAU,IAAI,OAAO,WAAW,GAAG;AAE1C;AAAA,MACF;AAEA,YAAM,aAAa,IAAI,OAAO,CAAC;AAG/B,YAAM,gBAAgB,cAAc,IAAI,UAAU;AAElD,UAAI,iBAAiB,cAAc,SAAS,GAAG;AAE7C,mBAAW,YAAY,eAAe;AACpC,cAAI;AACF,kBAAM,UAAU,eAAe;AAAA,cAC7B,KAAK,CAAC,QAAQ;AAAA,cACd,MAAM,IAAI;AAAA,cACV,QAAQ,IAAI;AAAA,YACd,CAAC;AAGD,sBAAU,KAAK;AAAA,cACb,iBAAiB,IAAI,WAAW;AAAA,cAChC,WAAW,QAAQ;AAAA,cACnB,MAAM,QAAQ;AAAA,cACd,UAAU,IAAI,YAAY;AAAA,YAC5B,CAAC;AAGD,gBAAI,YAAY,SAAS,WAAW,SAAS,QAAQ,SAAS,GAAG;AAC/D,6BAAe,QAAQ,SAAS,IAAI,QAAQ;AAC5C,kCAAoB;AAAA,YACtB;AAEA;AAAA,UACF,QAAQ;AAEN;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,kBAAU,KAAK;AAAA,UACb,iBAAiB,IAAI,WAAW;AAAA,UAChC,WAAW;AAAA,UACX,MAAM,EAAE,QAAQ,YAAY,MAAM,IAAI,KAAK;AAAA,UAC3C,UAAU,IAAI,YAAY;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,MAAM,kBAAkB;AAAA,IACxB,MAAM,kBAAkB;AAAA,IACxB,UAAU;AAAA,IACV,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
@@ -86,7 +86,7 @@ class SchemaValidator {
86
86
  validateDataSchemaAgainstMetaSchema(schema) {
87
87
  const isValid = this.dataSchemaValidator(schema);
88
88
  if (!isValid) {
89
- const errors = this.dataSchemaValidator.errors || [];
89
+ const errors = this.dataSchemaValidator.errors ?? [];
90
90
  const errorMessage = `Data schema validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(", ")}`;
91
91
  throw new SchemaValidationError(errorMessage, errors);
92
92
  }
@@ -142,7 +142,7 @@ class SchemaValidator {
142
142
  const dataValidator = this.ajv.compile(schema.schema);
143
143
  const isValid = dataValidator(data);
144
144
  if (!isValid) {
145
- const errors = dataValidator.errors || [];
145
+ const errors = dataValidator.errors ?? [];
146
146
  const errorMessage = `Data validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(", ")}`;
147
147
  throw new SchemaValidationError(errorMessage, errors);
148
148
  }
@@ -212,8 +212,8 @@ class SchemaValidator {
212
212
  */
213
213
  async fetchAndValidateSchema(url, downloadRelayer) {
214
214
  try {
215
- const { fetchWithRelayer } = await import("./download");
216
- const response = await fetchWithRelayer(url, downloadRelayer);
215
+ const { universalFetch } = await import("./download");
216
+ const response = await universalFetch(url, downloadRelayer);
217
217
  if (!response.ok) {
218
218
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
219
219
  }
@@ -241,7 +241,7 @@ function validateDataSchemaAgainstMetaSchema(schema) {
241
241
  return schema;
242
242
  }
243
243
  function validateDataAgainstSchema(data, schema) {
244
- return schemaValidator.validateDataAgainstSchema(data, schema);
244
+ schemaValidator.validateDataAgainstSchema(data, schema);
245
245
  }
246
246
  function fetchAndValidateSchema(url, downloadRelayer) {
247
247
  return schemaValidator.fetchAndValidateSchema(url, downloadRelayer);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/schemaValidation.ts"],"sourcesContent":["import Ajv, { type ValidateFunction } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport dataSchemaSchema from \"../schemas/dataSchema.schema.json\";\nimport type { Schema } from \"../types/data\";\n\n/**\n * Data schema interface following the Vana schema specification\n *\n * @category Configuration\n */\nexport interface DataSchema {\n /** The name of the data schema */\n name: string;\n /** The version of the data schema */\n version: string;\n /** Optional description of the data schema */\n description?: string;\n /** The dialect type - either SQLite or JSON */\n dialect: \"sqlite\" | \"json\";\n /** Optional version of the dialect */\n dialectVersion?: string;\n /** The actual schema definition as string or object */\n schema: string | object;\n}\n\n/**\n * Error thrown when schema validation fails\n */\nexport class SchemaValidationError extends Error {\n constructor(\n message: string,\n public errors: Array<{\n instancePath: string;\n schemaPath: string;\n keyword: string;\n params: Record<string, unknown>;\n message?: string;\n }>,\n ) {\n super(message);\n this.name = \"SchemaValidationError\";\n }\n}\n\n/**\n * Data schema validation utility class\n */\nexport class SchemaValidator {\n private ajv: Ajv;\n private dataSchemaValidator: ValidateFunction;\n\n constructor() {\n this.ajv = new Ajv({\n allErrors: true,\n verbose: true,\n strict: false,\n });\n\n // Add format validation (e.g., date, email, uri)\n addFormats(this.ajv);\n\n // Compile the data schema meta-schema validator\n this.dataSchemaValidator = this.ajv.compile(dataSchemaSchema);\n }\n\n /**\n * Validates a data schema definition against the Vana meta-schema\n *\n * @param schema - The data schema definition to validate\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n *\n * const schema = {\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: {\n * type: \"object\",\n * properties: {\n * name: { type: \"string\" },\n * age: { type: \"number\" }\n * }\n * }\n * };\n *\n * validator.validateDataSchemaAgainstMetaSchema(schema); // throws if invalid\n * ```\n */\n validateDataSchemaAgainstMetaSchema(\n schema: unknown,\n ): asserts schema is DataSchema {\n const isValid = this.dataSchemaValidator(schema);\n\n if (!isValid) {\n const errors = this.dataSchemaValidator.errors || [];\n const errorMessage = `Data schema validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(\", \")}`;\n throw new SchemaValidationError(errorMessage, errors);\n }\n\n // Additional validation based on dialect\n const typedSchema = schema as DataSchema;\n if (\n typedSchema.dialect === \"json\" &&\n typeof typedSchema.schema === \"object\"\n ) {\n // Validate that the embedded JSON Schema is actually valid\n try {\n this.ajv.compile(typedSchema.schema);\n } catch (error) {\n const errorMessage = `Invalid JSON Schema in data schema: ${error instanceof Error ? error.message : \"Unknown schema compilation error\"}`;\n throw new SchemaValidationError(errorMessage, []);\n }\n } else if (\n typedSchema.dialect === \"sqlite\" &&\n typeof typedSchema.schema === \"string\"\n ) {\n // Validate SQLite DDL syntax\n this.validateSQLiteDDL(typedSchema.schema, typedSchema.dialectVersion);\n }\n }\n\n /**\n * Validates data against a JSON Schema\n *\n * @param data - The data to validate\n * @param schema - The schema containing the validation rules (must have been validated or fetched from chain)\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n *\n * // Works with Schema from schemas.get()\n * const schema = await vana.schemas.get(1);\n * validator.validateDataAgainstSchema(userData, schema);\n *\n * // Also works with pre-validated DataSchema object\n * const dataSchema = validator.validateDataSchemaAgainstMetaSchema({\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: { type: \"object\", properties: { name: { type: \"string\" } } }\n * });\n * validator.validateDataAgainstSchema(userData, dataSchema);\n * ```\n */\n validateDataAgainstSchema(data: unknown, schema: DataSchema | Schema): void {\n if (schema.dialect !== \"json\") {\n console.warn(\n `[SchemaValidator] Data validation skipped: dialect '${schema.dialect}' does not support data validation. ` +\n `Only JSON schemas can validate data structure.`,\n );\n return;\n }\n\n if (typeof schema.schema !== \"object\") {\n throw new SchemaValidationError(\n \"JSON dialect schemas must have an object schema\",\n [],\n );\n }\n\n // Compile and validate against the data schema\n const dataValidator = this.ajv.compile(schema.schema);\n const isValid = dataValidator(data);\n\n if (!isValid) {\n const errors = dataValidator.errors || [];\n const errorMessage = `Data validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(\", \")}`;\n throw new SchemaValidationError(errorMessage, errors);\n }\n }\n\n /**\n * Validates a SQLite DDL string for basic syntax\n * Note: This is a basic validation, full SQL parsing would require a proper SQL parser\n *\n * @param ddl - The DDL string to validate\n * @param dialectVersion - Optional SQLite version (e.g., \"3\" for SQLite v3)\n * @throws SchemaValidationError if invalid\n */\n validateSQLiteDDL(ddl: string, dialectVersion?: string): void {\n if (typeof ddl !== \"string\" || ddl.trim().length === 0) {\n throw new SchemaValidationError(\n \"SQLite DDL must be a non-empty string\",\n [],\n );\n }\n\n // Validate dialectVersion if provided\n if (dialectVersion !== undefined) {\n const supportedVersions = [\"3\"];\n if (!supportedVersions.includes(dialectVersion)) {\n throw new SchemaValidationError(\n `Unsupported SQLite dialect version: ${dialectVersion}. Supported versions: ${supportedVersions.join(\", \")}`,\n [],\n );\n }\n }\n\n // Basic validation - check for CREATE TABLE statements\n const normalizedDDL = ddl.trim().toUpperCase();\n if (!normalizedDDL.includes(\"CREATE TABLE\")) {\n throw new SchemaValidationError(\n \"SQLite DDL must contain at least one CREATE TABLE statement\",\n [],\n );\n }\n\n // Check for balanced parentheses\n let parenCount = 0;\n for (const char of ddl) {\n if (char === \"(\") parenCount++;\n if (char === \")\") parenCount--;\n if (parenCount < 0) {\n throw new SchemaValidationError(\n \"SQLite DDL has unbalanced parentheses\",\n [],\n );\n }\n }\n\n if (parenCount !== 0) {\n throw new SchemaValidationError(\n \"SQLite DDL has unbalanced parentheses\",\n [],\n );\n }\n }\n\n /**\n * Fetches and validates a data schema from a URL\n *\n * @param url - The URL to fetch the data schema from\n * @param downloadRelayer - Optional download relayer for CORS bypass\n * @param downloadRelayer.proxyDownload - Function to proxy downloads through application server\n * @returns The validated data schema\n * @throws SchemaValidationError if invalid or fetch fails\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n * const schema = await validator.fetchAndValidateSchema(\"https://example.com/schema.json\");\n * ```\n */\n async fetchAndValidateSchema(\n url: string,\n downloadRelayer?: { proxyDownload: (url: string) => Promise<Blob> },\n ): Promise<DataSchema> {\n try {\n const { fetchWithRelayer } = await import(\"./download\");\n const response = await fetchWithRelayer(url, downloadRelayer);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const schema = await response.json();\n this.validateDataSchemaAgainstMetaSchema(schema);\n\n // Additional validation based on dialect\n if (schema.dialect === \"sqlite\" && typeof schema.schema === \"string\") {\n this.validateSQLiteDDL(schema.schema, schema.dialectVersion);\n }\n\n return schema;\n } catch (error) {\n if (error instanceof SchemaValidationError) {\n throw error;\n }\n\n throw new SchemaValidationError(\n `Failed to fetch and validate schema from ${url}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n [],\n );\n }\n }\n}\n\n/**\n * Global schema validator instance\n */\nexport const schemaValidator = new SchemaValidator();\n\n/**\n * Convenience function to validate a data schema definition against the Vana meta-schema\n *\n * @param schema - The data schema definition to validate\n * @returns The validated DataSchema\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const schemaDefinition = {\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: { type: \"object\", properties: { name: { type: \"string\" } } }\n * };\n *\n * const validatedSchema = validateDataSchemaAgainstMetaSchema(schemaDefinition);\n * ```\n */\nexport function validateDataSchemaAgainstMetaSchema(\n schema: unknown,\n): DataSchema {\n const validator: SchemaValidator = schemaValidator;\n validator.validateDataSchemaAgainstMetaSchema(schema);\n // If we get here, schema is valid and typed as DataSchema\n return schema as DataSchema;\n}\n\n/**\n * Convenience function to validate data against a schema\n *\n * @param data - The data to validate\n * @param schema - The data schema containing the schema\n * @returns void - Function doesn't return a value\n * @throws SchemaValidationError if invalid\n */\nexport function validateDataAgainstSchema(\n data: unknown,\n schema: DataSchema | Schema,\n): void {\n return schemaValidator.validateDataAgainstSchema(data, schema);\n}\n\n/**\n * Convenience function to fetch and validate a data schema from a URL\n *\n * @param url - The URL to fetch the data schema from\n * @param downloadRelayer - Optional download relayer for CORS bypass\n * @param downloadRelayer.proxyDownload - Function to proxy downloads through application server\n * @returns The validated data schema\n * @throws SchemaValidationError if invalid or fetch fails\n */\nexport function fetchAndValidateSchema(\n url: string,\n downloadRelayer?: { proxyDownload: (url: string) => Promise<Blob> },\n): Promise<DataSchema> {\n return schemaValidator.fetchAndValidateSchema(url, downloadRelayer);\n}\n"],"mappings":"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","names":["Ajv","addFormats","dataSchemaSchema"]}
1
+ {"version":3,"sources":["../../src/utils/schemaValidation.ts"],"sourcesContent":["import Ajv, { type ValidateFunction } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport dataSchemaSchema from \"../schemas/dataSchema.schema.json\";\nimport type { Schema } from \"../types/data\";\n\n/**\n * Data schema interface following the Vana schema specification\n *\n * @category Configuration\n */\nexport interface DataSchema {\n /** The name of the data schema */\n name: string;\n /** The version of the data schema */\n version: string;\n /** Optional description of the data schema */\n description?: string;\n /** The dialect type - either SQLite or JSON */\n dialect: \"sqlite\" | \"json\";\n /** Optional version of the dialect */\n dialectVersion?: string;\n /** The actual schema definition as string or object */\n schema: string | object;\n}\n\n/**\n * Error thrown when schema validation fails\n */\nexport class SchemaValidationError extends Error {\n constructor(\n message: string,\n public errors: Array<{\n instancePath: string;\n schemaPath: string;\n keyword: string;\n params: Record<string, unknown>;\n message?: string;\n }>,\n ) {\n super(message);\n this.name = \"SchemaValidationError\";\n }\n}\n\n/**\n * Data schema validation utility class\n */\nexport class SchemaValidator {\n private ajv: Ajv;\n private dataSchemaValidator: ValidateFunction;\n\n constructor() {\n this.ajv = new Ajv({\n allErrors: true,\n verbose: true,\n strict: false,\n });\n\n // Add format validation (e.g., date, email, uri)\n addFormats(this.ajv);\n\n // Compile the data schema meta-schema validator\n this.dataSchemaValidator = this.ajv.compile(dataSchemaSchema);\n }\n\n /**\n * Validates a data schema definition against the Vana meta-schema\n *\n * @param schema - The data schema definition to validate\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n *\n * const schema = {\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: {\n * type: \"object\",\n * properties: {\n * name: { type: \"string\" },\n * age: { type: \"number\" }\n * }\n * }\n * };\n *\n * validator.validateDataSchemaAgainstMetaSchema(schema); // throws if invalid\n * ```\n */\n validateDataSchemaAgainstMetaSchema(\n schema: unknown,\n ): asserts schema is DataSchema {\n const isValid = this.dataSchemaValidator(schema);\n\n if (!isValid) {\n const errors = this.dataSchemaValidator.errors ?? [];\n const errorMessage = `Data schema validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(\", \")}`;\n throw new SchemaValidationError(errorMessage, errors);\n }\n\n // Additional validation based on dialect\n const typedSchema = schema as DataSchema;\n if (\n typedSchema.dialect === \"json\" &&\n typeof typedSchema.schema === \"object\"\n ) {\n // Validate that the embedded JSON Schema is actually valid\n try {\n this.ajv.compile(typedSchema.schema);\n } catch (error) {\n const errorMessage = `Invalid JSON Schema in data schema: ${error instanceof Error ? error.message : \"Unknown schema compilation error\"}`;\n throw new SchemaValidationError(errorMessage, []);\n }\n } else if (\n typedSchema.dialect === \"sqlite\" &&\n typeof typedSchema.schema === \"string\"\n ) {\n // Validate SQLite DDL syntax\n this.validateSQLiteDDL(typedSchema.schema, typedSchema.dialectVersion);\n }\n }\n\n /**\n * Validates data against a JSON Schema\n *\n * @param data - The data to validate\n * @param schema - The schema containing the validation rules (must have been validated or fetched from chain)\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n *\n * // Works with Schema from schemas.get()\n * const schema = await vana.schemas.get(1);\n * validator.validateDataAgainstSchema(userData, schema);\n *\n * // Also works with pre-validated DataSchema object\n * const dataSchema = validator.validateDataSchemaAgainstMetaSchema({\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: { type: \"object\", properties: { name: { type: \"string\" } } }\n * });\n * validator.validateDataAgainstSchema(userData, dataSchema);\n * ```\n */\n validateDataAgainstSchema(data: unknown, schema: DataSchema | Schema): void {\n if (schema.dialect !== \"json\") {\n console.warn(\n `[SchemaValidator] Data validation skipped: dialect '${schema.dialect}' does not support data validation. ` +\n `Only JSON schemas can validate data structure.`,\n );\n return;\n }\n\n if (typeof schema.schema !== \"object\") {\n throw new SchemaValidationError(\n \"JSON dialect schemas must have an object schema\",\n [],\n );\n }\n\n // Compile and validate against the data schema\n const dataValidator = this.ajv.compile(schema.schema);\n const isValid = dataValidator(data);\n\n if (!isValid) {\n const errors = dataValidator.errors ?? [];\n const errorMessage = `Data validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(\", \")}`;\n throw new SchemaValidationError(errorMessage, errors);\n }\n }\n\n /**\n * Validates a SQLite DDL string for basic syntax\n * Note: This is a basic validation, full SQL parsing would require a proper SQL parser\n *\n * @param ddl - The DDL string to validate\n * @param dialectVersion - Optional SQLite version (e.g., \"3\" for SQLite v3)\n * @throws SchemaValidationError if invalid\n */\n validateSQLiteDDL(ddl: string, dialectVersion?: string): void {\n if (typeof ddl !== \"string\" || ddl.trim().length === 0) {\n throw new SchemaValidationError(\n \"SQLite DDL must be a non-empty string\",\n [],\n );\n }\n\n // Validate dialectVersion if provided\n if (dialectVersion !== undefined) {\n const supportedVersions = [\"3\"];\n if (!supportedVersions.includes(dialectVersion)) {\n throw new SchemaValidationError(\n `Unsupported SQLite dialect version: ${dialectVersion}. Supported versions: ${supportedVersions.join(\", \")}`,\n [],\n );\n }\n }\n\n // Basic validation - check for CREATE TABLE statements\n const normalizedDDL = ddl.trim().toUpperCase();\n if (!normalizedDDL.includes(\"CREATE TABLE\")) {\n throw new SchemaValidationError(\n \"SQLite DDL must contain at least one CREATE TABLE statement\",\n [],\n );\n }\n\n // Check for balanced parentheses\n let parenCount = 0;\n for (const char of ddl) {\n if (char === \"(\") parenCount++;\n if (char === \")\") parenCount--;\n if (parenCount < 0) {\n throw new SchemaValidationError(\n \"SQLite DDL has unbalanced parentheses\",\n [],\n );\n }\n }\n\n if (parenCount !== 0) {\n throw new SchemaValidationError(\n \"SQLite DDL has unbalanced parentheses\",\n [],\n );\n }\n }\n\n /**\n * Fetches and validates a data schema from a URL\n *\n * @param url - The URL to fetch the data schema from\n * @param downloadRelayer - Optional download relayer for CORS bypass\n * @param downloadRelayer.proxyDownload - Function to proxy downloads through application server\n * @returns The validated data schema\n * @throws SchemaValidationError if invalid or fetch fails\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n * const schema = await validator.fetchAndValidateSchema(\"https://example.com/schema.json\");\n * ```\n */\n async fetchAndValidateSchema(\n url: string,\n downloadRelayer?: { proxyDownload: (url: string) => Promise<Blob> },\n ): Promise<DataSchema> {\n try {\n const { universalFetch } = await import(\"./download\");\n const response = await universalFetch(url, downloadRelayer);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const schema = await response.json();\n this.validateDataSchemaAgainstMetaSchema(schema);\n\n // Additional validation based on dialect\n if (schema.dialect === \"sqlite\" && typeof schema.schema === \"string\") {\n this.validateSQLiteDDL(schema.schema, schema.dialectVersion);\n }\n\n return schema;\n } catch (error) {\n if (error instanceof SchemaValidationError) {\n throw error;\n }\n\n throw new SchemaValidationError(\n `Failed to fetch and validate schema from ${url}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n [],\n );\n }\n }\n}\n\n/**\n * Global schema validator instance\n */\nexport const schemaValidator = new SchemaValidator();\n\n/**\n * Convenience function to validate a data schema definition against the Vana meta-schema\n *\n * @param schema - The data schema definition to validate\n * @returns The validated DataSchema\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const schemaDefinition = {\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: { type: \"object\", properties: { name: { type: \"string\" } } }\n * };\n *\n * const validatedSchema = validateDataSchemaAgainstMetaSchema(schemaDefinition);\n * ```\n */\nexport function validateDataSchemaAgainstMetaSchema(\n schema: unknown,\n): DataSchema {\n const validator: SchemaValidator = schemaValidator;\n validator.validateDataSchemaAgainstMetaSchema(schema);\n // If we get here, schema is valid and typed as DataSchema\n return schema;\n}\n\n/**\n * Convenience function to validate data against a schema\n *\n * @param data - The data to validate\n * @param schema - The data schema containing the schema\n * @returns void - Function doesn't return a value\n * @throws SchemaValidationError if invalid\n */\nexport function validateDataAgainstSchema(\n data: unknown,\n schema: DataSchema | Schema,\n): void {\n schemaValidator.validateDataAgainstSchema(data, schema);\n}\n\n/**\n * Convenience function to fetch and validate a data schema from a URL\n *\n * @param url - The URL to fetch the data schema from\n * @param downloadRelayer - Optional download relayer for CORS bypass\n * @param downloadRelayer.proxyDownload - Function to proxy downloads through application server\n * @returns The validated data schema\n * @throws SchemaValidationError if invalid or fetch fails\n */\nexport function fetchAndValidateSchema(\n url: string,\n downloadRelayer?: { proxyDownload: (url: string) => Promise<Blob> },\n): Promise<DataSchema> {\n return schemaValidator.fetchAndValidateSchema(url, downloadRelayer);\n}\n"],"mappings":"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","names":["Ajv","addFormats","dataSchemaSchema"]}
@@ -1,12 +1,10 @@
1
- import { Schema } from '../types/data.js';
2
- import 'viem';
3
-
1
+ import type { Schema } from "../types/data";
4
2
  /**
5
3
  * Data schema interface following the Vana schema specification
6
4
  *
7
5
  * @category Configuration
8
6
  */
9
- interface DataSchema {
7
+ export interface DataSchema {
10
8
  /** The name of the data schema */
11
9
  name: string;
12
10
  /** The version of the data schema */
@@ -23,7 +21,7 @@ interface DataSchema {
23
21
  /**
24
22
  * Error thrown when schema validation fails
25
23
  */
26
- declare class SchemaValidationError extends Error {
24
+ export declare class SchemaValidationError extends Error {
27
25
  errors: Array<{
28
26
  instancePath: string;
29
27
  schemaPath: string;
@@ -42,7 +40,7 @@ declare class SchemaValidationError extends Error {
42
40
  /**
43
41
  * Data schema validation utility class
44
42
  */
45
- declare class SchemaValidator {
43
+ export declare class SchemaValidator {
46
44
  private ajv;
47
45
  private dataSchemaValidator;
48
46
  constructor();
@@ -127,7 +125,7 @@ declare class SchemaValidator {
127
125
  /**
128
126
  * Global schema validator instance
129
127
  */
130
- declare const schemaValidator: SchemaValidator;
128
+ export declare const schemaValidator: SchemaValidator;
131
129
  /**
132
130
  * Convenience function to validate a data schema definition against the Vana meta-schema
133
131
  *
@@ -146,7 +144,7 @@ declare const schemaValidator: SchemaValidator;
146
144
  * const validatedSchema = validateDataSchemaAgainstMetaSchema(schemaDefinition);
147
145
  * ```
148
146
  */
149
- declare function validateDataSchemaAgainstMetaSchema(schema: unknown): DataSchema;
147
+ export declare function validateDataSchemaAgainstMetaSchema(schema: unknown): DataSchema;
150
148
  /**
151
149
  * Convenience function to validate data against a schema
152
150
  *
@@ -155,7 +153,7 @@ declare function validateDataSchemaAgainstMetaSchema(schema: unknown): DataSchem
155
153
  * @returns void - Function doesn't return a value
156
154
  * @throws SchemaValidationError if invalid
157
155
  */
158
- declare function validateDataAgainstSchema(data: unknown, schema: DataSchema | Schema): void;
156
+ export declare function validateDataAgainstSchema(data: unknown, schema: DataSchema | Schema): void;
159
157
  /**
160
158
  * Convenience function to fetch and validate a data schema from a URL
161
159
  *
@@ -165,8 +163,6 @@ declare function validateDataAgainstSchema(data: unknown, schema: DataSchema | S
165
163
  * @returns The validated data schema
166
164
  * @throws SchemaValidationError if invalid or fetch fails
167
165
  */
168
- declare function fetchAndValidateSchema(url: string, downloadRelayer?: {
166
+ export declare function fetchAndValidateSchema(url: string, downloadRelayer?: {
169
167
  proxyDownload: (url: string) => Promise<Blob>;
170
168
  }): Promise<DataSchema>;
171
-
172
- export { type DataSchema, SchemaValidationError, SchemaValidator, fetchAndValidateSchema, schemaValidator, validateDataAgainstSchema, validateDataSchemaAgainstMetaSchema };
@@ -1,6 +1,3 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
1
  import Ajv from "ajv";
5
2
  import addFormats from "ajv-formats";
6
3
  import dataSchemaSchema from "../schemas/dataSchema.schema.json";
@@ -12,9 +9,9 @@ class SchemaValidationError extends Error {
12
9
  }
13
10
  }
14
11
  class SchemaValidator {
12
+ ajv;
13
+ dataSchemaValidator;
15
14
  constructor() {
16
- __publicField(this, "ajv");
17
- __publicField(this, "dataSchemaValidator");
18
15
  this.ajv = new Ajv({
19
16
  allErrors: true,
20
17
  verbose: true,
@@ -51,7 +48,7 @@ class SchemaValidator {
51
48
  validateDataSchemaAgainstMetaSchema(schema) {
52
49
  const isValid = this.dataSchemaValidator(schema);
53
50
  if (!isValid) {
54
- const errors = this.dataSchemaValidator.errors || [];
51
+ const errors = this.dataSchemaValidator.errors ?? [];
55
52
  const errorMessage = `Data schema validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(", ")}`;
56
53
  throw new SchemaValidationError(errorMessage, errors);
57
54
  }
@@ -107,7 +104,7 @@ class SchemaValidator {
107
104
  const dataValidator = this.ajv.compile(schema.schema);
108
105
  const isValid = dataValidator(data);
109
106
  if (!isValid) {
110
- const errors = dataValidator.errors || [];
107
+ const errors = dataValidator.errors ?? [];
111
108
  const errorMessage = `Data validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(", ")}`;
112
109
  throw new SchemaValidationError(errorMessage, errors);
113
110
  }
@@ -177,8 +174,8 @@ class SchemaValidator {
177
174
  */
178
175
  async fetchAndValidateSchema(url, downloadRelayer) {
179
176
  try {
180
- const { fetchWithRelayer } = await import("./download");
181
- const response = await fetchWithRelayer(url, downloadRelayer);
177
+ const { universalFetch } = await import("./download");
178
+ const response = await universalFetch(url, downloadRelayer);
182
179
  if (!response.ok) {
183
180
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
184
181
  }
@@ -206,7 +203,7 @@ function validateDataSchemaAgainstMetaSchema(schema) {
206
203
  return schema;
207
204
  }
208
205
  function validateDataAgainstSchema(data, schema) {
209
- return schemaValidator.validateDataAgainstSchema(data, schema);
206
+ schemaValidator.validateDataAgainstSchema(data, schema);
210
207
  }
211
208
  function fetchAndValidateSchema(url, downloadRelayer) {
212
209
  return schemaValidator.fetchAndValidateSchema(url, downloadRelayer);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/schemaValidation.ts"],"sourcesContent":["import Ajv, { type ValidateFunction } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport dataSchemaSchema from \"../schemas/dataSchema.schema.json\";\nimport type { Schema } from \"../types/data\";\n\n/**\n * Data schema interface following the Vana schema specification\n *\n * @category Configuration\n */\nexport interface DataSchema {\n /** The name of the data schema */\n name: string;\n /** The version of the data schema */\n version: string;\n /** Optional description of the data schema */\n description?: string;\n /** The dialect type - either SQLite or JSON */\n dialect: \"sqlite\" | \"json\";\n /** Optional version of the dialect */\n dialectVersion?: string;\n /** The actual schema definition as string or object */\n schema: string | object;\n}\n\n/**\n * Error thrown when schema validation fails\n */\nexport class SchemaValidationError extends Error {\n constructor(\n message: string,\n public errors: Array<{\n instancePath: string;\n schemaPath: string;\n keyword: string;\n params: Record<string, unknown>;\n message?: string;\n }>,\n ) {\n super(message);\n this.name = \"SchemaValidationError\";\n }\n}\n\n/**\n * Data schema validation utility class\n */\nexport class SchemaValidator {\n private ajv: Ajv;\n private dataSchemaValidator: ValidateFunction;\n\n constructor() {\n this.ajv = new Ajv({\n allErrors: true,\n verbose: true,\n strict: false,\n });\n\n // Add format validation (e.g., date, email, uri)\n addFormats(this.ajv);\n\n // Compile the data schema meta-schema validator\n this.dataSchemaValidator = this.ajv.compile(dataSchemaSchema);\n }\n\n /**\n * Validates a data schema definition against the Vana meta-schema\n *\n * @param schema - The data schema definition to validate\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n *\n * const schema = {\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: {\n * type: \"object\",\n * properties: {\n * name: { type: \"string\" },\n * age: { type: \"number\" }\n * }\n * }\n * };\n *\n * validator.validateDataSchemaAgainstMetaSchema(schema); // throws if invalid\n * ```\n */\n validateDataSchemaAgainstMetaSchema(\n schema: unknown,\n ): asserts schema is DataSchema {\n const isValid = this.dataSchemaValidator(schema);\n\n if (!isValid) {\n const errors = this.dataSchemaValidator.errors || [];\n const errorMessage = `Data schema validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(\", \")}`;\n throw new SchemaValidationError(errorMessage, errors);\n }\n\n // Additional validation based on dialect\n const typedSchema = schema as DataSchema;\n if (\n typedSchema.dialect === \"json\" &&\n typeof typedSchema.schema === \"object\"\n ) {\n // Validate that the embedded JSON Schema is actually valid\n try {\n this.ajv.compile(typedSchema.schema);\n } catch (error) {\n const errorMessage = `Invalid JSON Schema in data schema: ${error instanceof Error ? error.message : \"Unknown schema compilation error\"}`;\n throw new SchemaValidationError(errorMessage, []);\n }\n } else if (\n typedSchema.dialect === \"sqlite\" &&\n typeof typedSchema.schema === \"string\"\n ) {\n // Validate SQLite DDL syntax\n this.validateSQLiteDDL(typedSchema.schema, typedSchema.dialectVersion);\n }\n }\n\n /**\n * Validates data against a JSON Schema\n *\n * @param data - The data to validate\n * @param schema - The schema containing the validation rules (must have been validated or fetched from chain)\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n *\n * // Works with Schema from schemas.get()\n * const schema = await vana.schemas.get(1);\n * validator.validateDataAgainstSchema(userData, schema);\n *\n * // Also works with pre-validated DataSchema object\n * const dataSchema = validator.validateDataSchemaAgainstMetaSchema({\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: { type: \"object\", properties: { name: { type: \"string\" } } }\n * });\n * validator.validateDataAgainstSchema(userData, dataSchema);\n * ```\n */\n validateDataAgainstSchema(data: unknown, schema: DataSchema | Schema): void {\n if (schema.dialect !== \"json\") {\n console.warn(\n `[SchemaValidator] Data validation skipped: dialect '${schema.dialect}' does not support data validation. ` +\n `Only JSON schemas can validate data structure.`,\n );\n return;\n }\n\n if (typeof schema.schema !== \"object\") {\n throw new SchemaValidationError(\n \"JSON dialect schemas must have an object schema\",\n [],\n );\n }\n\n // Compile and validate against the data schema\n const dataValidator = this.ajv.compile(schema.schema);\n const isValid = dataValidator(data);\n\n if (!isValid) {\n const errors = dataValidator.errors || [];\n const errorMessage = `Data validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(\", \")}`;\n throw new SchemaValidationError(errorMessage, errors);\n }\n }\n\n /**\n * Validates a SQLite DDL string for basic syntax\n * Note: This is a basic validation, full SQL parsing would require a proper SQL parser\n *\n * @param ddl - The DDL string to validate\n * @param dialectVersion - Optional SQLite version (e.g., \"3\" for SQLite v3)\n * @throws SchemaValidationError if invalid\n */\n validateSQLiteDDL(ddl: string, dialectVersion?: string): void {\n if (typeof ddl !== \"string\" || ddl.trim().length === 0) {\n throw new SchemaValidationError(\n \"SQLite DDL must be a non-empty string\",\n [],\n );\n }\n\n // Validate dialectVersion if provided\n if (dialectVersion !== undefined) {\n const supportedVersions = [\"3\"];\n if (!supportedVersions.includes(dialectVersion)) {\n throw new SchemaValidationError(\n `Unsupported SQLite dialect version: ${dialectVersion}. Supported versions: ${supportedVersions.join(\", \")}`,\n [],\n );\n }\n }\n\n // Basic validation - check for CREATE TABLE statements\n const normalizedDDL = ddl.trim().toUpperCase();\n if (!normalizedDDL.includes(\"CREATE TABLE\")) {\n throw new SchemaValidationError(\n \"SQLite DDL must contain at least one CREATE TABLE statement\",\n [],\n );\n }\n\n // Check for balanced parentheses\n let parenCount = 0;\n for (const char of ddl) {\n if (char === \"(\") parenCount++;\n if (char === \")\") parenCount--;\n if (parenCount < 0) {\n throw new SchemaValidationError(\n \"SQLite DDL has unbalanced parentheses\",\n [],\n );\n }\n }\n\n if (parenCount !== 0) {\n throw new SchemaValidationError(\n \"SQLite DDL has unbalanced parentheses\",\n [],\n );\n }\n }\n\n /**\n * Fetches and validates a data schema from a URL\n *\n * @param url - The URL to fetch the data schema from\n * @param downloadRelayer - Optional download relayer for CORS bypass\n * @param downloadRelayer.proxyDownload - Function to proxy downloads through application server\n * @returns The validated data schema\n * @throws SchemaValidationError if invalid or fetch fails\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n * const schema = await validator.fetchAndValidateSchema(\"https://example.com/schema.json\");\n * ```\n */\n async fetchAndValidateSchema(\n url: string,\n downloadRelayer?: { proxyDownload: (url: string) => Promise<Blob> },\n ): Promise<DataSchema> {\n try {\n const { fetchWithRelayer } = await import(\"./download\");\n const response = await fetchWithRelayer(url, downloadRelayer);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const schema = await response.json();\n this.validateDataSchemaAgainstMetaSchema(schema);\n\n // Additional validation based on dialect\n if (schema.dialect === \"sqlite\" && typeof schema.schema === \"string\") {\n this.validateSQLiteDDL(schema.schema, schema.dialectVersion);\n }\n\n return schema;\n } catch (error) {\n if (error instanceof SchemaValidationError) {\n throw error;\n }\n\n throw new SchemaValidationError(\n `Failed to fetch and validate schema from ${url}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n [],\n );\n }\n }\n}\n\n/**\n * Global schema validator instance\n */\nexport const schemaValidator = new SchemaValidator();\n\n/**\n * Convenience function to validate a data schema definition against the Vana meta-schema\n *\n * @param schema - The data schema definition to validate\n * @returns The validated DataSchema\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const schemaDefinition = {\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: { type: \"object\", properties: { name: { type: \"string\" } } }\n * };\n *\n * const validatedSchema = validateDataSchemaAgainstMetaSchema(schemaDefinition);\n * ```\n */\nexport function validateDataSchemaAgainstMetaSchema(\n schema: unknown,\n): DataSchema {\n const validator: SchemaValidator = schemaValidator;\n validator.validateDataSchemaAgainstMetaSchema(schema);\n // If we get here, schema is valid and typed as DataSchema\n return schema as DataSchema;\n}\n\n/**\n * Convenience function to validate data against a schema\n *\n * @param data - The data to validate\n * @param schema - The data schema containing the schema\n * @returns void - Function doesn't return a value\n * @throws SchemaValidationError if invalid\n */\nexport function validateDataAgainstSchema(\n data: unknown,\n schema: DataSchema | Schema,\n): void {\n return schemaValidator.validateDataAgainstSchema(data, schema);\n}\n\n/**\n * Convenience function to fetch and validate a data schema from a URL\n *\n * @param url - The URL to fetch the data schema from\n * @param downloadRelayer - Optional download relayer for CORS bypass\n * @param downloadRelayer.proxyDownload - Function to proxy downloads through application server\n * @returns The validated data schema\n * @throws SchemaValidationError if invalid or fetch fails\n */\nexport function fetchAndValidateSchema(\n url: string,\n downloadRelayer?: { proxyDownload: (url: string) => Promise<Blob> },\n): Promise<DataSchema> {\n return schemaValidator.fetchAndValidateSchema(url, downloadRelayer);\n}\n"],"mappings":";;;AAAA,OAAO,SAAoC;AAC3C,OAAO,gBAAgB;AACvB,OAAO,sBAAsB;AA0BtB,MAAM,8BAA8B,MAAM;AAAA,EAC/C,YACE,SACO,QAOP;AACA,UAAM,OAAO;AARN;AASP,SAAK,OAAO;AAAA,EACd;AACF;AAKO,MAAM,gBAAgB;AAAA,EAI3B,cAAc;AAHd,wBAAQ;AACR,wBAAQ;AAGN,SAAK,MAAM,IAAI,IAAI;AAAA,MACjB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAGD,eAAW,KAAK,GAAG;AAGnB,SAAK,sBAAsB,KAAK,IAAI,QAAQ,gBAAgB;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2BA,oCACE,QAC8B;AAC9B,UAAM,UAAU,KAAK,oBAAoB,MAAM;AAE/C,QAAI,CAAC,SAAS;AACZ,YAAM,SAAS,KAAK,oBAAoB,UAAU,CAAC;AACnD,YAAM,eAAe,kCAAkC,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,YAAY,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC;AACrH,YAAM,IAAI,sBAAsB,cAAc,MAAM;AAAA,IACtD;AAGA,UAAM,cAAc;AACpB,QACE,YAAY,YAAY,UACxB,OAAO,YAAY,WAAW,UAC9B;AAEA,UAAI;AACF,aAAK,IAAI,QAAQ,YAAY,MAAM;AAAA,MACrC,SAAS,OAAO;AACd,cAAM,eAAe,uCAAuC,iBAAiB,QAAQ,MAAM,UAAU,kCAAkC;AACvI,cAAM,IAAI,sBAAsB,cAAc,CAAC,CAAC;AAAA,MAClD;AAAA,IACF,WACE,YAAY,YAAY,YACxB,OAAO,YAAY,WAAW,UAC9B;AAEA,WAAK,kBAAkB,YAAY,QAAQ,YAAY,cAAc;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,0BAA0B,MAAe,QAAmC;AAC1E,QAAI,OAAO,YAAY,QAAQ;AAC7B,cAAQ;AAAA,QACN,uDAAuD,OAAO,OAAO;AAAA,MAEvE;AACA;AAAA,IACF;AAEA,QAAI,OAAO,OAAO,WAAW,UAAU;AACrC,YAAM,IAAI;AAAA,QACR;AAAA,QACA,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,gBAAgB,KAAK,IAAI,QAAQ,OAAO,MAAM;AACpD,UAAM,UAAU,cAAc,IAAI;AAElC,QAAI,CAAC,SAAS;AACZ,YAAM,SAAS,cAAc,UAAU,CAAC;AACxC,YAAM,eAAe,2BAA2B,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,YAAY,IAAI,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC;AAC9G,YAAM,IAAI,sBAAsB,cAAc,MAAM;AAAA,IACtD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,kBAAkB,KAAa,gBAA+B;AAC5D,QAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,EAAE,WAAW,GAAG;AACtD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,mBAAmB,QAAW;AAChC,YAAM,oBAAoB,CAAC,GAAG;AAC9B,UAAI,CAAC,kBAAkB,SAAS,cAAc,GAAG;AAC/C,cAAM,IAAI;AAAA,UACR,uCAAuC,cAAc,yBAAyB,kBAAkB,KAAK,IAAI,CAAC;AAAA,UAC1G,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,UAAM,gBAAgB,IAAI,KAAK,EAAE,YAAY;AAC7C,QAAI,CAAC,cAAc,SAAS,cAAc,GAAG;AAC3C,YAAM,IAAI;AAAA,QACR;AAAA,QACA,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,aAAa;AACjB,eAAW,QAAQ,KAAK;AACtB,UAAI,SAAS,IAAK;AAClB,UAAI,SAAS,IAAK;AAClB,UAAI,aAAa,GAAG;AAClB,cAAM,IAAI;AAAA,UACR;AAAA,UACA,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAe,GAAG;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,uBACJ,KACA,iBACqB;AACrB,QAAI;AACF,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,YAAY;AACtD,YAAM,WAAW,MAAM,iBAAiB,KAAK,eAAe;AAC5D,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,MACnE;AAEA,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAK,oCAAoC,MAAM;AAG/C,UAAI,OAAO,YAAY,YAAY,OAAO,OAAO,WAAW,UAAU;AACpE,aAAK,kBAAkB,OAAO,QAAQ,OAAO,cAAc;AAAA,MAC7D;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,uBAAuB;AAC1C,cAAM;AAAA,MACR;AAEA,YAAM,IAAI;AAAA,QACR,4CAA4C,GAAG,KAAK,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,QAC5G,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAKO,MAAM,kBAAkB,IAAI,gBAAgB;AAoB5C,SAAS,oCACd,QACY;AACZ,QAAM,YAA6B;AACnC,YAAU,oCAAoC,MAAM;AAEpD,SAAO;AACT;AAUO,SAAS,0BACd,MACA,QACM;AACN,SAAO,gBAAgB,0BAA0B,MAAM,MAAM;AAC/D;AAWO,SAAS,uBACd,KACA,iBACqB;AACrB,SAAO,gBAAgB,uBAAuB,KAAK,eAAe;AACpE;","names":[]}
1
+ {"version":3,"sources":["../../src/utils/schemaValidation.ts"],"sourcesContent":["import Ajv, { type ValidateFunction } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport dataSchemaSchema from \"../schemas/dataSchema.schema.json\";\nimport type { Schema } from \"../types/data\";\n\n/**\n * Data schema interface following the Vana schema specification\n *\n * @category Configuration\n */\nexport interface DataSchema {\n /** The name of the data schema */\n name: string;\n /** The version of the data schema */\n version: string;\n /** Optional description of the data schema */\n description?: string;\n /** The dialect type - either SQLite or JSON */\n dialect: \"sqlite\" | \"json\";\n /** Optional version of the dialect */\n dialectVersion?: string;\n /** The actual schema definition as string or object */\n schema: string | object;\n}\n\n/**\n * Error thrown when schema validation fails\n */\nexport class SchemaValidationError extends Error {\n constructor(\n message: string,\n public errors: Array<{\n instancePath: string;\n schemaPath: string;\n keyword: string;\n params: Record<string, unknown>;\n message?: string;\n }>,\n ) {\n super(message);\n this.name = \"SchemaValidationError\";\n }\n}\n\n/**\n * Data schema validation utility class\n */\nexport class SchemaValidator {\n private ajv: Ajv;\n private dataSchemaValidator: ValidateFunction;\n\n constructor() {\n this.ajv = new Ajv({\n allErrors: true,\n verbose: true,\n strict: false,\n });\n\n // Add format validation (e.g., date, email, uri)\n addFormats(this.ajv);\n\n // Compile the data schema meta-schema validator\n this.dataSchemaValidator = this.ajv.compile(dataSchemaSchema);\n }\n\n /**\n * Validates a data schema definition against the Vana meta-schema\n *\n * @param schema - The data schema definition to validate\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n *\n * const schema = {\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: {\n * type: \"object\",\n * properties: {\n * name: { type: \"string\" },\n * age: { type: \"number\" }\n * }\n * }\n * };\n *\n * validator.validateDataSchemaAgainstMetaSchema(schema); // throws if invalid\n * ```\n */\n validateDataSchemaAgainstMetaSchema(\n schema: unknown,\n ): asserts schema is DataSchema {\n const isValid = this.dataSchemaValidator(schema);\n\n if (!isValid) {\n const errors = this.dataSchemaValidator.errors ?? [];\n const errorMessage = `Data schema validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(\", \")}`;\n throw new SchemaValidationError(errorMessage, errors);\n }\n\n // Additional validation based on dialect\n const typedSchema = schema as DataSchema;\n if (\n typedSchema.dialect === \"json\" &&\n typeof typedSchema.schema === \"object\"\n ) {\n // Validate that the embedded JSON Schema is actually valid\n try {\n this.ajv.compile(typedSchema.schema);\n } catch (error) {\n const errorMessage = `Invalid JSON Schema in data schema: ${error instanceof Error ? error.message : \"Unknown schema compilation error\"}`;\n throw new SchemaValidationError(errorMessage, []);\n }\n } else if (\n typedSchema.dialect === \"sqlite\" &&\n typeof typedSchema.schema === \"string\"\n ) {\n // Validate SQLite DDL syntax\n this.validateSQLiteDDL(typedSchema.schema, typedSchema.dialectVersion);\n }\n }\n\n /**\n * Validates data against a JSON Schema\n *\n * @param data - The data to validate\n * @param schema - The schema containing the validation rules (must have been validated or fetched from chain)\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n *\n * // Works with Schema from schemas.get()\n * const schema = await vana.schemas.get(1);\n * validator.validateDataAgainstSchema(userData, schema);\n *\n * // Also works with pre-validated DataSchema object\n * const dataSchema = validator.validateDataSchemaAgainstMetaSchema({\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: { type: \"object\", properties: { name: { type: \"string\" } } }\n * });\n * validator.validateDataAgainstSchema(userData, dataSchema);\n * ```\n */\n validateDataAgainstSchema(data: unknown, schema: DataSchema | Schema): void {\n if (schema.dialect !== \"json\") {\n console.warn(\n `[SchemaValidator] Data validation skipped: dialect '${schema.dialect}' does not support data validation. ` +\n `Only JSON schemas can validate data structure.`,\n );\n return;\n }\n\n if (typeof schema.schema !== \"object\") {\n throw new SchemaValidationError(\n \"JSON dialect schemas must have an object schema\",\n [],\n );\n }\n\n // Compile and validate against the data schema\n const dataValidator = this.ajv.compile(schema.schema);\n const isValid = dataValidator(data);\n\n if (!isValid) {\n const errors = dataValidator.errors ?? [];\n const errorMessage = `Data validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(\", \")}`;\n throw new SchemaValidationError(errorMessage, errors);\n }\n }\n\n /**\n * Validates a SQLite DDL string for basic syntax\n * Note: This is a basic validation, full SQL parsing would require a proper SQL parser\n *\n * @param ddl - The DDL string to validate\n * @param dialectVersion - Optional SQLite version (e.g., \"3\" for SQLite v3)\n * @throws SchemaValidationError if invalid\n */\n validateSQLiteDDL(ddl: string, dialectVersion?: string): void {\n if (typeof ddl !== \"string\" || ddl.trim().length === 0) {\n throw new SchemaValidationError(\n \"SQLite DDL must be a non-empty string\",\n [],\n );\n }\n\n // Validate dialectVersion if provided\n if (dialectVersion !== undefined) {\n const supportedVersions = [\"3\"];\n if (!supportedVersions.includes(dialectVersion)) {\n throw new SchemaValidationError(\n `Unsupported SQLite dialect version: ${dialectVersion}. Supported versions: ${supportedVersions.join(\", \")}`,\n [],\n );\n }\n }\n\n // Basic validation - check for CREATE TABLE statements\n const normalizedDDL = ddl.trim().toUpperCase();\n if (!normalizedDDL.includes(\"CREATE TABLE\")) {\n throw new SchemaValidationError(\n \"SQLite DDL must contain at least one CREATE TABLE statement\",\n [],\n );\n }\n\n // Check for balanced parentheses\n let parenCount = 0;\n for (const char of ddl) {\n if (char === \"(\") parenCount++;\n if (char === \")\") parenCount--;\n if (parenCount < 0) {\n throw new SchemaValidationError(\n \"SQLite DDL has unbalanced parentheses\",\n [],\n );\n }\n }\n\n if (parenCount !== 0) {\n throw new SchemaValidationError(\n \"SQLite DDL has unbalanced parentheses\",\n [],\n );\n }\n }\n\n /**\n * Fetches and validates a data schema from a URL\n *\n * @param url - The URL to fetch the data schema from\n * @param downloadRelayer - Optional download relayer for CORS bypass\n * @param downloadRelayer.proxyDownload - Function to proxy downloads through application server\n * @returns The validated data schema\n * @throws SchemaValidationError if invalid or fetch fails\n * @example\n * ```typescript\n * const validator = new SchemaValidator();\n * const schema = await validator.fetchAndValidateSchema(\"https://example.com/schema.json\");\n * ```\n */\n async fetchAndValidateSchema(\n url: string,\n downloadRelayer?: { proxyDownload: (url: string) => Promise<Blob> },\n ): Promise<DataSchema> {\n try {\n const { universalFetch } = await import(\"./download\");\n const response = await universalFetch(url, downloadRelayer);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const schema = await response.json();\n this.validateDataSchemaAgainstMetaSchema(schema);\n\n // Additional validation based on dialect\n if (schema.dialect === \"sqlite\" && typeof schema.schema === \"string\") {\n this.validateSQLiteDDL(schema.schema, schema.dialectVersion);\n }\n\n return schema;\n } catch (error) {\n if (error instanceof SchemaValidationError) {\n throw error;\n }\n\n throw new SchemaValidationError(\n `Failed to fetch and validate schema from ${url}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n [],\n );\n }\n }\n}\n\n/**\n * Global schema validator instance\n */\nexport const schemaValidator = new SchemaValidator();\n\n/**\n * Convenience function to validate a data schema definition against the Vana meta-schema\n *\n * @param schema - The data schema definition to validate\n * @returns The validated DataSchema\n * @throws SchemaValidationError if invalid\n * @example\n * ```typescript\n * const schemaDefinition = {\n * name: \"User Profile\",\n * version: \"1.0.0\",\n * dialect: \"json\",\n * schema: { type: \"object\", properties: { name: { type: \"string\" } } }\n * };\n *\n * const validatedSchema = validateDataSchemaAgainstMetaSchema(schemaDefinition);\n * ```\n */\nexport function validateDataSchemaAgainstMetaSchema(\n schema: unknown,\n): DataSchema {\n const validator: SchemaValidator = schemaValidator;\n validator.validateDataSchemaAgainstMetaSchema(schema);\n // If we get here, schema is valid and typed as DataSchema\n return schema;\n}\n\n/**\n * Convenience function to validate data against a schema\n *\n * @param data - The data to validate\n * @param schema - The data schema containing the schema\n * @returns void - Function doesn't return a value\n * @throws SchemaValidationError if invalid\n */\nexport function validateDataAgainstSchema(\n data: unknown,\n schema: DataSchema | Schema,\n): void {\n schemaValidator.validateDataAgainstSchema(data, schema);\n}\n\n/**\n * Convenience function to fetch and validate a data schema from a URL\n *\n * @param url - The URL to fetch the data schema from\n * @param downloadRelayer - Optional download relayer for CORS bypass\n * @param downloadRelayer.proxyDownload - Function to proxy downloads through application server\n * @returns The validated data schema\n * @throws SchemaValidationError if invalid or fetch fails\n */\nexport function fetchAndValidateSchema(\n url: string,\n downloadRelayer?: { proxyDownload: (url: string) => Promise<Blob> },\n): Promise<DataSchema> {\n return schemaValidator.fetchAndValidateSchema(url, downloadRelayer);\n}\n"],"mappings":"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","names":[]}
@@ -24,7 +24,6 @@ __export(signatureCache_exports, {
24
24
  module.exports = __toCommonJS(signatureCache_exports);
25
25
  var import_viem = require("viem");
26
26
  var import_sha256 = require("@noble/hashes/sha256");
27
- var import_utils = require("@noble/hashes/utils");
28
27
  class SignatureCache {
29
28
  static PREFIX = "vana_sig_";
30
29
  static DEFAULT_TTL_HOURS = 2;
@@ -143,15 +142,21 @@ class SignatureCache {
143
142
  static hashMessage(message) {
144
143
  const jsonString = JSON.stringify(message, this.deterministicReplacer);
145
144
  const hashBytes = (0, import_sha256.sha256)(new TextEncoder().encode(jsonString));
146
- return (0, import_utils.bytesToHex)(hashBytes);
145
+ return (0, import_viem.toHex)(hashBytes);
147
146
  }
148
147
  /**
149
- * Deterministic JSON replacer that handles BigInt values and sorts object keys
150
- * This ensures consistent cache key generation for EIP-712 typed data
148
+ * Deterministic JSON replacer for consistent cache key generation.
149
+ *
150
+ * @remarks
151
+ * Handles BigInt serialization and sorts object keys to ensure
152
+ * identical objects always produce the same hash regardless of
153
+ * property order.
151
154
  *
152
155
  * @param _key - The object key being serialized (unused)
153
156
  * @param value - The value to serialize
154
157
  * @returns The serialized value with sorted keys for objects
158
+ *
159
+ * @internal
155
160
  */
156
161
  static deterministicReplacer(_key, value) {
157
162
  if (typeof value === "bigint") {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/signatureCache.ts"],"sourcesContent":["import { Hash, getAddress } from \"viem\";\nimport type { VanaCacheAdapter } from \"../platform/interface\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\n\ninterface CachedSignature {\n signature: Hash;\n expires: number;\n}\n\n/**\n * Simple signature cache using platform cache adapter to avoid repeated signing of identical messages.\n *\n * @remarks\n * This cache significantly improves UX by avoiding repeated wallet signature prompts\n * for identical operations. It's particularly useful for operations that may be\n * retried or called multiple times with the same parameters.\n *\n * Features:\n * - Platform-appropriate storage (sessionStorage in browser, memory in Node.js)\n * - Configurable TTL (default 2 hours)\n * - Automatic cleanup of expired entries\n * - Cache keys based on wallet address + message hash\n *\n * @example\n * ```typescript\n * // Check cache before requesting signature\n * const cached = SignatureCache.get(cache, walletAddress, messageHash);\n * if (cached) {\n * return cached;\n * }\n *\n * // Request signature and cache it\n * const signature = await wallet.signTypedData(typedData);\n * SignatureCache.set(cache, walletAddress, messageHash, signature);\n * ```\n * @category Utilities\n */\nexport class SignatureCache {\n private static readonly PREFIX = \"vana_sig_\";\n private static readonly DEFAULT_TTL_HOURS = 2;\n\n /**\n * Get a cached signature if it exists and hasn't expired\n *\n * @param cache - Platform cache adapter instance\n * @param walletAddress - Wallet address that created the signature\n * @param messageHash - Hash of the message that was signed\n * @returns The cached signature if valid, null if expired or not found\n * @example\n * ```typescript\n * const messageHash = SignatureCache.hashMessage(typedData);\n * const cached = SignatureCache.get(cache, '0x123...', messageHash);\n * if (cached) {\n * console.log('Using cached signature:', cached);\n * }\n * ```\n */\n static get(\n cache: VanaCacheAdapter,\n walletAddress: string,\n messageHash: string,\n ): Hash | null {\n const key = this.getCacheKey(walletAddress, messageHash);\n\n try {\n const stored = cache.get(key);\n if (!stored) return null;\n\n const cached: CachedSignature = JSON.parse(stored);\n\n // Check if expired\n if (Date.now() > cached.expires) {\n cache.delete(key);\n return null;\n }\n\n return cached.signature;\n } catch {\n // Invalid JSON or storage error, clean up\n try {\n cache.delete(key);\n } catch {\n // Ignore cache cleanup errors\n }\n return null;\n }\n }\n\n /**\n * Store a signature in the cache with configurable TTL\n *\n * @param cache - Platform cache adapter instance\n * @param walletAddress - Wallet address that created the signature\n * @param messageHash - Hash of the message that was signed\n * @param signature - The signature to cache\n * @param ttlHours - Time to live in hours (default: 2)\n * @example\n * ```typescript\n * const signature = await wallet.signTypedData(typedData);\n * const messageHash = SignatureCache.hashMessage(typedData);\n *\n * // Cache for default 2 hours\n * SignatureCache.set(cache, walletAddress, messageHash, signature);\n *\n * // Cache for 24 hours\n * SignatureCache.set(cache, walletAddress, messageHash, signature, 24);\n * ```\n */\n static set(\n cache: VanaCacheAdapter,\n walletAddress: string,\n messageHash: string,\n signature: Hash,\n ttlHours: number = this.DEFAULT_TTL_HOURS,\n ): void {\n const key = this.getCacheKey(walletAddress, messageHash);\n const cached: CachedSignature = {\n signature,\n expires: Date.now() + ttlHours * 3600000, // Convert hours to milliseconds\n };\n\n try {\n cache.set(key, JSON.stringify(cached));\n } catch {\n // Storage quota exceeded or other error, ignore silently\n // Better to continue without caching than to fail\n }\n }\n\n /**\n * Clear all cached signatures (useful for testing or explicit cleanup)\n *\n * @param cache - Platform cache adapter instance\n * @example\n * ```typescript\n * // Clear all signatures when user logs out\n * SignatureCache.clear(cache);\n *\n * // Clear before running tests\n * beforeEach(() => {\n * SignatureCache.clear(cache);\n * });\n * ```\n */\n static clear(cache: VanaCacheAdapter): void {\n try {\n cache.clear();\n } catch {\n // Ignore storage errors\n }\n }\n\n private static getCacheKey(\n walletAddress: string,\n messageHash: string,\n ): string {\n return `${this.PREFIX}${getAddress(walletAddress)}:${messageHash}`;\n }\n\n /**\n * Generate a deterministic hash of a message object for cache key generation\n *\n * @remarks\n * Creates a cryptographically secure hash from complex objects including EIP-712 typed data.\n * Uses SHA-256 for collision resistance and deterministic key generation.\n * Handles BigInt serialization and sorts object keys for consistency.\n *\n * @param message - The message object to hash (typically EIP-712 typed data)\n * @returns A hex string hash (SHA-256) suitable for cache keys\n * @example\n * ```typescript\n * const typedData = {\n * domain: { name: 'Vana', version: '1' },\n * message: { nonce: 123n, grant: '...' }\n * };\n *\n * const hash = SignatureCache.hashMessage(typedData);\n * // Returns SHA-256 hash like: \"a1b2c3d4e5f6...\"\n * ```\n */\n static hashMessage(message: object): string {\n // Deterministically stringify the object with sorted keys\n const jsonString = JSON.stringify(message, this.deterministicReplacer);\n\n // Use SHA-256 for cryptographic hashing\n const hashBytes = sha256(new TextEncoder().encode(jsonString));\n return bytesToHex(hashBytes);\n }\n\n /**\n * Deterministic JSON replacer that handles BigInt values and sorts object keys\n * This ensures consistent cache key generation for EIP-712 typed data\n *\n * @param _key - The object key being serialized (unused)\n * @param value - The value to serialize\n * @returns The serialized value with sorted keys for objects\n */\n private static deterministicReplacer(_key: string, value: unknown): unknown {\n if (typeof value === \"bigint\") {\n return `__BIGINT__${value.toString()}`;\n }\n // Sort object keys for deterministic serialization\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.keys(value as Record<string, unknown>)\n .sort()\n .reduce(\n (sorted, key) => {\n sorted[key] = (value as Record<string, unknown>)[key];\n return sorted;\n },\n {} as Record<string, unknown>,\n );\n }\n return value;\n }\n}\n\n/**\n * Wrapper function to cache signature operations\n *\n * @param cache - The cache adapter to use for storage\n * @param walletAddress - The wallet address signing the message\n * @param typedData - The EIP-712 typed data being signed\n * @param signFn - Function that performs the actual signing\n * @param ttlHours - Cache TTL in hours (default 2)\n * @returns The signature (cached or newly generated)\n */\nexport async function withSignatureCache(\n cache: VanaCacheAdapter,\n walletAddress: string,\n typedData: Record<string, unknown>,\n signFn: () => Promise<Hash>,\n ttlHours?: number,\n): Promise<Hash> {\n // Create a hash of the typed data for the cache key\n const messageHash = SignatureCache.hashMessage(typedData);\n\n // Try to get from cache first\n const cached = SignatureCache.get(cache, walletAddress, messageHash);\n if (cached) {\n return cached;\n }\n\n // Not in cache, sign and store\n const signature = await signFn();\n SignatureCache.set(cache, walletAddress, messageHash, signature, ttlHours);\n\n return signature;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/utils/signatureCache.ts"],"sourcesContent":["/**\n * Provides signature caching to improve UX by avoiding repeated wallet prompts.\n *\n * @remarks\n * This module implements a secure signature cache that stores signed messages\n * temporarily to avoid repeatedly prompting users for the same signature.\n * It uses platform-appropriate storage (sessionStorage in browser, memory in Node.js)\n * and includes automatic expiration and cleanup.\n *\n * @category Utilities\n * @module utils/signatureCache\n */\n\nimport type { Hash } from \"viem\";\nimport { getAddress, toHex } from \"viem\";\nimport type { VanaCacheAdapter } from \"../platform/interface\";\nimport { sha256 } from \"@noble/hashes/sha256\";\n\n/**\n * Represents a cached signature with expiration metadata.\n *\n * @internal\n */\ninterface CachedSignature {\n /** The cached signature hash */\n signature: Hash;\n /** Unix timestamp when this cache entry expires */\n expires: number;\n}\n\n/**\n * Simple signature cache using platform cache adapter to avoid repeated signing of identical messages.\n *\n * @remarks\n * This cache significantly improves UX by avoiding repeated wallet signature prompts\n * for identical operations. It's particularly useful for operations that may be\n * retried or called multiple times with the same parameters.\n *\n * Features:\n * - Platform-appropriate storage (sessionStorage in browser, memory in Node.js)\n * - Configurable TTL (default 2 hours)\n * - Automatic cleanup of expired entries\n * - Cache keys based on wallet address + message hash\n *\n * @example\n * ```typescript\n * // Check cache before requesting signature\n * const cached = SignatureCache.get(cache, walletAddress, messageHash);\n * if (cached) {\n * return cached;\n * }\n *\n * // Request signature and cache it\n * const signature = await wallet.signTypedData(typedData);\n * SignatureCache.set(cache, walletAddress, messageHash, signature);\n * ```\n * @category Utilities\n */\nexport class SignatureCache {\n private static readonly PREFIX = \"vana_sig_\";\n private static readonly DEFAULT_TTL_HOURS = 2;\n\n /**\n * Get a cached signature if it exists and hasn't expired\n *\n * @param cache - Platform cache adapter instance\n * @param walletAddress - Wallet address that created the signature\n * @param messageHash - Hash of the message that was signed\n * @returns The cached signature if valid, null if expired or not found\n * @example\n * ```typescript\n * const messageHash = SignatureCache.hashMessage(typedData);\n * const cached = SignatureCache.get(cache, '0x123...', messageHash);\n * if (cached) {\n * console.log('Using cached signature:', cached);\n * }\n * ```\n */\n static get(\n cache: VanaCacheAdapter,\n walletAddress: string,\n messageHash: string,\n ): Hash | null {\n const key = this.getCacheKey(walletAddress, messageHash);\n\n try {\n const stored = cache.get(key);\n if (!stored) return null;\n\n const cached: CachedSignature = JSON.parse(stored);\n\n // Check if expired\n if (Date.now() > cached.expires) {\n cache.delete(key);\n return null;\n }\n\n return cached.signature;\n } catch {\n // Invalid JSON or storage error, clean up\n try {\n cache.delete(key);\n } catch {\n // Ignore cache cleanup errors\n }\n return null;\n }\n }\n\n /**\n * Store a signature in the cache with configurable TTL\n *\n * @param cache - Platform cache adapter instance\n * @param walletAddress - Wallet address that created the signature\n * @param messageHash - Hash of the message that was signed\n * @param signature - The signature to cache\n * @param ttlHours - Time to live in hours (default: 2)\n * @example\n * ```typescript\n * const signature = await wallet.signTypedData(typedData);\n * const messageHash = SignatureCache.hashMessage(typedData);\n *\n * // Cache for default 2 hours\n * SignatureCache.set(cache, walletAddress, messageHash, signature);\n *\n * // Cache for 24 hours\n * SignatureCache.set(cache, walletAddress, messageHash, signature, 24);\n * ```\n */\n static set(\n cache: VanaCacheAdapter,\n walletAddress: string,\n messageHash: string,\n signature: Hash,\n ttlHours: number = this.DEFAULT_TTL_HOURS,\n ): void {\n const key = this.getCacheKey(walletAddress, messageHash);\n const cached: CachedSignature = {\n signature,\n expires: Date.now() + ttlHours * 3600000, // Convert hours to milliseconds\n };\n\n try {\n cache.set(key, JSON.stringify(cached));\n } catch {\n // Storage quota exceeded or other error, ignore silently\n // Better to continue without caching than to fail\n }\n }\n\n /**\n * Clear all cached signatures (useful for testing or explicit cleanup)\n *\n * @param cache - Platform cache adapter instance\n * @example\n * ```typescript\n * // Clear all signatures when user logs out\n * SignatureCache.clear(cache);\n *\n * // Clear before running tests\n * beforeEach(() => {\n * SignatureCache.clear(cache);\n * });\n * ```\n */\n static clear(cache: VanaCacheAdapter): void {\n try {\n cache.clear();\n } catch {\n // Ignore storage errors\n }\n }\n\n private static getCacheKey(\n walletAddress: string,\n messageHash: string,\n ): string {\n return `${this.PREFIX}${getAddress(walletAddress)}:${messageHash}`;\n }\n\n /**\n * Generate a deterministic hash of a message object for cache key generation\n *\n * @remarks\n * Creates a cryptographically secure hash from complex objects including EIP-712 typed data.\n * Uses SHA-256 for collision resistance and deterministic key generation.\n * Handles BigInt serialization and sorts object keys for consistency.\n *\n * @param message - The message object to hash (typically EIP-712 typed data)\n * @returns A hex string hash (SHA-256) suitable for cache keys\n * @example\n * ```typescript\n * const typedData = {\n * domain: { name: 'Vana', version: '1' },\n * message: { nonce: 123n, grant: '...' }\n * };\n *\n * const hash = SignatureCache.hashMessage(typedData);\n * // Returns SHA-256 hash like: \"a1b2c3d4e5f6...\"\n * ```\n */\n static hashMessage(message: object): string {\n // Deterministically stringify the object with sorted keys\n const jsonString = JSON.stringify(message, this.deterministicReplacer);\n\n // Use SHA-256 for cryptographic hashing\n const hashBytes = sha256(new TextEncoder().encode(jsonString));\n return toHex(hashBytes);\n }\n\n /**\n * Deterministic JSON replacer for consistent cache key generation.\n *\n * @remarks\n * Handles BigInt serialization and sorts object keys to ensure\n * identical objects always produce the same hash regardless of\n * property order.\n *\n * @param _key - The object key being serialized (unused)\n * @param value - The value to serialize\n * @returns The serialized value with sorted keys for objects\n *\n * @internal\n */\n private static deterministicReplacer(_key: string, value: unknown): unknown {\n if (typeof value === \"bigint\") {\n return `__BIGINT__${value.toString()}`;\n }\n // Sort object keys for deterministic serialization\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.keys(value as Record<string, unknown>)\n .sort()\n .reduce(\n (sorted, key) => {\n sorted[key] = (value as Record<string, unknown>)[key];\n return sorted;\n },\n {} as Record<string, unknown>,\n );\n }\n return value;\n }\n}\n\n/**\n * Wraps signature operations with caching to avoid repeated prompts.\n *\n * @remarks\n * This helper function checks the cache before requesting a signature\n * and stores new signatures for future use. It significantly improves\n * UX for operations that may be retried or called multiple times.\n *\n * @param cache - The cache adapter to use for storage.\n * Obtain from platform adapter.\n * @param walletAddress - The wallet address signing the message.\n * Obtain from wallet connection.\n * @param typedData - The EIP-712 typed data being signed.\n * Typically permission or grant data.\n * @param signFn - Async function that performs the actual signing.\n * Usually calls wallet.signTypedData().\n * @param ttlHours - Cache TTL in hours.\n * Defaults to 2 hours.\n * @returns The signature (cached or newly generated)\n *\n * @example\n * ```typescript\n * const signature = await withSignatureCache(\n * platformAdapter.cache,\n * walletAddress,\n * typedData,\n * async () => wallet.signTypedData(typedData),\n * 24 // Cache for 24 hours\n * );\n * ```\n *\n * @category Utilities\n */\nexport async function withSignatureCache(\n cache: VanaCacheAdapter,\n walletAddress: string,\n typedData: Record<string, unknown>,\n signFn: () => Promise<Hash>,\n ttlHours?: number,\n): Promise<Hash> {\n // Create a hash of the typed data for the cache key\n const messageHash = SignatureCache.hashMessage(typedData);\n\n // Try to get from cache first\n const cached = SignatureCache.get(cache, walletAddress, messageHash);\n if (cached) {\n return cached;\n }\n\n // Not in cache, sign and store\n const signature = await signFn();\n SignatureCache.set(cache, walletAddress, messageHash, signature, ttlHours);\n\n return signature;\n}\n"],"mappings":"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","names":[]}