@opendatalabs/vana-sdk 2.2.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (622) hide show
  1. package/README.md +76 -92
  2. package/dist/auth/errors.cjs +54 -0
  3. package/dist/auth/errors.cjs.map +1 -0
  4. package/dist/auth/errors.d.ts +26 -0
  5. package/dist/auth/errors.js +28 -0
  6. package/dist/auth/errors.js.map +1 -0
  7. package/dist/auth/pkce.cjs +100 -0
  8. package/dist/auth/pkce.cjs.map +1 -0
  9. package/dist/auth/pkce.d.ts +55 -0
  10. package/dist/auth/pkce.js +71 -0
  11. package/dist/auth/pkce.js.map +1 -0
  12. package/dist/auth/token-store.cjs +59 -0
  13. package/dist/auth/token-store.cjs.map +1 -0
  14. package/dist/auth/token-store.d.ts +61 -0
  15. package/dist/auth/token-store.js +35 -0
  16. package/dist/auth/token-store.js.map +1 -0
  17. package/dist/auth/web3-signed-builder.cjs +70 -0
  18. package/dist/auth/web3-signed-builder.cjs.map +1 -0
  19. package/dist/auth/web3-signed-builder.d.ts +47 -0
  20. package/dist/auth/web3-signed-builder.js +45 -0
  21. package/dist/auth/web3-signed-builder.js.map +1 -0
  22. package/dist/auth/web3-signed.cjs +125 -0
  23. package/dist/auth/web3-signed.cjs.map +1 -0
  24. package/dist/auth/web3-signed.d.ts +59 -0
  25. package/dist/auth/web3-signed.js +104 -0
  26. package/dist/auth/web3-signed.js.map +1 -0
  27. package/dist/chains/definitions.cjs +2 -6
  28. package/dist/chains/definitions.cjs.map +1 -1
  29. package/dist/chains/definitions.d.ts +1 -7
  30. package/dist/chains/definitions.js +2 -6
  31. package/dist/chains/definitions.js.map +1 -1
  32. package/dist/config/chains.d.ts +18 -0
  33. package/dist/config/contracts.config.cjs +7 -95
  34. package/dist/config/contracts.config.cjs.map +1 -1
  35. package/dist/config/contracts.config.d.ts +0 -54
  36. package/dist/config/contracts.config.js +6 -93
  37. package/dist/config/contracts.config.js.map +1 -1
  38. package/dist/config/default-services.cjs +0 -10
  39. package/dist/config/default-services.cjs.map +1 -1
  40. package/dist/config/default-services.d.ts +1 -20
  41. package/dist/config/default-services.js +0 -9
  42. package/dist/config/default-services.js.map +1 -1
  43. package/dist/crypto/ecies/interface.cjs +2 -0
  44. package/dist/crypto/ecies/interface.cjs.map +1 -1
  45. package/dist/crypto/ecies/interface.js +2 -0
  46. package/dist/crypto/ecies/interface.js.map +1 -1
  47. package/dist/crypto/envelope/openpgp.cjs +59 -0
  48. package/dist/crypto/envelope/openpgp.cjs.map +1 -0
  49. package/dist/crypto/envelope/openpgp.d.ts +28 -0
  50. package/dist/crypto/envelope/openpgp.js +24 -0
  51. package/dist/crypto/envelope/openpgp.js.map +1 -0
  52. package/dist/crypto/keys/derive.cjs +65 -0
  53. package/dist/crypto/keys/derive.cjs.map +1 -0
  54. package/dist/crypto/keys/derive.d.ts +45 -0
  55. package/dist/crypto/keys/derive.js +38 -0
  56. package/dist/crypto/keys/derive.js.map +1 -0
  57. package/dist/errors.cjs +10 -0
  58. package/dist/errors.cjs.map +1 -1
  59. package/dist/errors.js +10 -0
  60. package/dist/errors.js.map +1 -1
  61. package/dist/generated/abi/VanaPoolEntityImplementation.cjs +65 -0
  62. package/dist/generated/abi/VanaPoolEntityImplementation.cjs.map +1 -1
  63. package/dist/generated/abi/VanaPoolEntityImplementation.d.ts +51 -0
  64. package/dist/generated/abi/VanaPoolEntityImplementation.js +65 -0
  65. package/dist/generated/abi/VanaPoolEntityImplementation.js.map +1 -1
  66. package/dist/generated/abi/VanaPoolStakingImplementation.cjs +187 -19
  67. package/dist/generated/abi/VanaPoolStakingImplementation.cjs.map +1 -1
  68. package/dist/generated/abi/VanaPoolStakingImplementation.d.ts +144 -14
  69. package/dist/generated/abi/VanaPoolStakingImplementation.js +187 -19
  70. package/dist/generated/abi/VanaPoolStakingImplementation.js.map +1 -1
  71. package/dist/generated/abi/index.cjs +2 -37
  72. package/dist/generated/abi/index.cjs.map +1 -1
  73. package/dist/generated/abi/index.d.ts +2687 -9119
  74. package/dist/generated/abi/index.js +2 -29
  75. package/dist/generated/abi/index.js.map +1 -1
  76. package/dist/generated/addresses.cjs +5 -107
  77. package/dist/generated/addresses.cjs.map +1 -1
  78. package/dist/generated/addresses.d.ts +5 -99
  79. package/dist/generated/addresses.js +5 -105
  80. package/dist/generated/addresses.js.map +1 -1
  81. package/dist/index.browser.d.ts +23 -138
  82. package/dist/index.browser.js +32090 -112
  83. package/dist/index.browser.js.map +7 -1
  84. package/dist/index.node.cjs +32809 -157
  85. package/dist/index.node.cjs.map +7 -1
  86. package/dist/index.node.d.ts +22 -208
  87. package/dist/index.node.js +32716 -131
  88. package/dist/index.node.js.map +7 -1
  89. package/dist/protocol/data-file.cjs +56 -0
  90. package/dist/protocol/data-file.cjs.map +1 -0
  91. package/dist/protocol/data-file.d.ts +20 -0
  92. package/dist/protocol/data-file.js +30 -0
  93. package/dist/protocol/data-file.js.map +1 -0
  94. package/dist/protocol/eip712.cjs +123 -0
  95. package/dist/protocol/eip712.cjs.map +1 -0
  96. package/dist/protocol/eip712.d.ts +117 -0
  97. package/dist/protocol/eip712.js +90 -0
  98. package/dist/protocol/eip712.js.map +1 -0
  99. package/dist/protocol/gateway.cjs +226 -0
  100. package/dist/protocol/gateway.cjs.map +1 -0
  101. package/dist/protocol/gateway.d.ts +120 -0
  102. package/dist/protocol/gateway.js +202 -0
  103. package/dist/protocol/gateway.js.map +1 -0
  104. package/dist/protocol/scopes.cjs +78 -0
  105. package/dist/protocol/scopes.cjs.map +1 -0
  106. package/dist/protocol/scopes.d.ts +13 -0
  107. package/dist/protocol/scopes.js +50 -0
  108. package/dist/protocol/scopes.js.map +1 -0
  109. package/dist/{types/atomicStore.cjs → storage/default.cjs} +9 -8
  110. package/dist/storage/default.cjs.map +1 -0
  111. package/dist/storage/default.d.ts +4 -0
  112. package/dist/storage/default.js +8 -0
  113. package/dist/storage/default.js.map +1 -0
  114. package/dist/storage/index.cjs +11 -2
  115. package/dist/storage/index.cjs.map +1 -1
  116. package/dist/storage/index.d.ts +9 -0
  117. package/dist/storage/index.js +7 -1
  118. package/dist/storage/index.js.map +1 -1
  119. package/dist/storage/providers/callback-storage.cjs +1 -0
  120. package/dist/storage/providers/callback-storage.cjs.map +1 -1
  121. package/dist/storage/providers/callback-storage.js +1 -0
  122. package/dist/storage/providers/callback-storage.js.map +1 -1
  123. package/dist/storage/providers/dropbox.cjs +1 -0
  124. package/dist/storage/providers/dropbox.cjs.map +1 -1
  125. package/dist/storage/providers/dropbox.js +1 -0
  126. package/dist/storage/providers/dropbox.js.map +1 -1
  127. package/dist/storage/providers/google-drive.cjs +1 -0
  128. package/dist/storage/providers/google-drive.cjs.map +1 -1
  129. package/dist/storage/providers/google-drive.js +1 -0
  130. package/dist/storage/providers/google-drive.js.map +1 -1
  131. package/dist/storage/providers/ipfs.cjs +1 -0
  132. package/dist/storage/providers/ipfs.cjs.map +1 -1
  133. package/dist/storage/providers/ipfs.js +1 -0
  134. package/dist/storage/providers/ipfs.js.map +1 -1
  135. package/dist/storage/providers/pinata.cjs +1 -0
  136. package/dist/storage/providers/pinata.cjs.map +1 -1
  137. package/dist/storage/providers/pinata.js +1 -0
  138. package/dist/storage/providers/pinata.js.map +1 -1
  139. package/dist/storage/providers/r2.cjs +376 -0
  140. package/dist/storage/providers/r2.cjs.map +1 -0
  141. package/dist/storage/providers/r2.d.ts +91 -0
  142. package/dist/storage/providers/r2.js +354 -0
  143. package/dist/storage/providers/r2.js.map +1 -0
  144. package/dist/storage/providers/vana-storage.cjs +251 -0
  145. package/dist/storage/providers/vana-storage.cjs.map +1 -0
  146. package/dist/storage/providers/vana-storage.d.ts +100 -0
  147. package/dist/storage/providers/vana-storage.js +231 -0
  148. package/dist/storage/providers/vana-storage.js.map +1 -0
  149. package/dist/types/config.cjs +0 -34
  150. package/dist/types/config.cjs.map +1 -1
  151. package/dist/types/config.d.ts +1 -607
  152. package/dist/types/config.js +0 -22
  153. package/dist/types/config.js.map +1 -1
  154. package/dist/types/contracts.cjs.map +1 -1
  155. package/dist/types/contracts.d.ts +1 -1
  156. package/dist/types/index.cjs +2 -33
  157. package/dist/types/index.cjs.map +1 -1
  158. package/dist/types/index.d.ts +2 -33
  159. package/dist/types/index.js +1 -35
  160. package/dist/types/index.js.map +1 -1
  161. package/dist/types/ps-errors.cjs +66 -0
  162. package/dist/types/ps-errors.cjs.map +1 -0
  163. package/dist/types/ps-errors.d.ts +25 -0
  164. package/dist/types/ps-errors.js +41 -0
  165. package/dist/types/ps-errors.js.map +1 -0
  166. package/dist/types.cjs.map +1 -1
  167. package/dist/types.d.ts +0 -29
  168. package/dist/types.js.map +1 -1
  169. package/package.json +7 -25
  170. package/dist/client/enhancedResponse.cjs +0 -164
  171. package/dist/client/enhancedResponse.cjs.map +0 -1
  172. package/dist/client/enhancedResponse.d.ts +0 -120
  173. package/dist/client/enhancedResponse.js +0 -138
  174. package/dist/client/enhancedResponse.js.map +0 -1
  175. package/dist/controllers/__tests__/data-consistency-integration.test.d.ts +0 -7
  176. package/dist/controllers/base.cjs +0 -116
  177. package/dist/controllers/base.cjs.map +0 -1
  178. package/dist/controllers/base.d.ts +0 -94
  179. package/dist/controllers/base.js +0 -92
  180. package/dist/controllers/base.js.map +0 -1
  181. package/dist/controllers/data.cjs +0 -2633
  182. package/dist/controllers/data.cjs.map +0 -1
  183. package/dist/controllers/data.d.ts +0 -1067
  184. package/dist/controllers/data.js +0 -2626
  185. package/dist/controllers/data.js.map +0 -1
  186. package/dist/controllers/operations.cjs +0 -430
  187. package/dist/controllers/operations.cjs.map +0 -1
  188. package/dist/controllers/operations.d.ts +0 -229
  189. package/dist/controllers/operations.js +0 -406
  190. package/dist/controllers/operations.js.map +0 -1
  191. package/dist/controllers/permissions.cjs +0 -4368
  192. package/dist/controllers/permissions.cjs.map +0 -1
  193. package/dist/controllers/permissions.d.ts +0 -1411
  194. package/dist/controllers/permissions.js +0 -4344
  195. package/dist/controllers/permissions.js.map +0 -1
  196. package/dist/controllers/protocol.cjs +0 -183
  197. package/dist/controllers/protocol.cjs.map +0 -1
  198. package/dist/controllers/protocol.d.ts +0 -138
  199. package/dist/controllers/protocol.js +0 -163
  200. package/dist/controllers/protocol.js.map +0 -1
  201. package/dist/controllers/schemas.cjs +0 -678
  202. package/dist/controllers/schemas.cjs.map +0 -1
  203. package/dist/controllers/schemas.d.ts +0 -293
  204. package/dist/controllers/schemas.js +0 -654
  205. package/dist/controllers/schemas.js.map +0 -1
  206. package/dist/controllers/server.cjs +0 -643
  207. package/dist/controllers/server.cjs.map +0 -1
  208. package/dist/controllers/server.d.ts +0 -322
  209. package/dist/controllers/server.js +0 -624
  210. package/dist/controllers/server.js.map +0 -1
  211. package/dist/core/__tests__/pollingManager.test.d.ts +0 -4
  212. package/dist/core/apiClient.cjs +0 -378
  213. package/dist/core/apiClient.cjs.map +0 -1
  214. package/dist/core/apiClient.d.ts +0 -286
  215. package/dist/core/apiClient.js +0 -359
  216. package/dist/core/apiClient.js.map +0 -1
  217. package/dist/core/generics.cjs +0 -417
  218. package/dist/core/generics.cjs.map +0 -1
  219. package/dist/core/generics.d.ts +0 -205
  220. package/dist/core/generics.js +0 -386
  221. package/dist/core/generics.js.map +0 -1
  222. package/dist/core/health.cjs +0 -289
  223. package/dist/core/health.cjs.map +0 -1
  224. package/dist/core/health.d.ts +0 -143
  225. package/dist/core/health.js +0 -265
  226. package/dist/core/health.js.map +0 -1
  227. package/dist/core/inMemoryNonceManager.cjs +0 -138
  228. package/dist/core/inMemoryNonceManager.cjs.map +0 -1
  229. package/dist/core/inMemoryNonceManager.d.ts +0 -69
  230. package/dist/core/inMemoryNonceManager.js +0 -114
  231. package/dist/core/inMemoryNonceManager.js.map +0 -1
  232. package/dist/core/nonceManager.cjs +0 -304
  233. package/dist/core/nonceManager.cjs.map +0 -1
  234. package/dist/core/nonceManager.d.ts +0 -116
  235. package/dist/core/nonceManager.js +0 -280
  236. package/dist/core/nonceManager.js.map +0 -1
  237. package/dist/core/pollingManager.cjs +0 -292
  238. package/dist/core/pollingManager.cjs.map +0 -1
  239. package/dist/core/pollingManager.d.ts +0 -120
  240. package/dist/core/pollingManager.js +0 -268
  241. package/dist/core/pollingManager.js.map +0 -1
  242. package/dist/core.cjs +0 -777
  243. package/dist/core.cjs.map +0 -1
  244. package/dist/core.d.ts +0 -493
  245. package/dist/core.js +0 -752
  246. package/dist/core.js.map +0 -1
  247. package/dist/diagnostics.cjs +0 -37
  248. package/dist/diagnostics.cjs.map +0 -1
  249. package/dist/diagnostics.d.ts +0 -24
  250. package/dist/diagnostics.js +0 -13
  251. package/dist/diagnostics.js.map +0 -1
  252. package/dist/diagnostics.test.d.ts +0 -1
  253. package/dist/generated/abi/DLPPerformanceImplementation.cjs +0 -1202
  254. package/dist/generated/abi/DLPPerformanceImplementation.cjs.map +0 -1
  255. package/dist/generated/abi/DLPPerformanceImplementation.d.ts +0 -914
  256. package/dist/generated/abi/DLPPerformanceImplementation.js +0 -1178
  257. package/dist/generated/abi/DLPPerformanceImplementation.js.map +0 -1
  258. package/dist/generated/abi/DLPRewardDeployerImplementation.cjs +0 -1112
  259. package/dist/generated/abi/DLPRewardDeployerImplementation.cjs.map +0 -1
  260. package/dist/generated/abi/DLPRewardDeployerImplementation.d.ts +0 -840
  261. package/dist/generated/abi/DLPRewardDeployerImplementation.js +0 -1088
  262. package/dist/generated/abi/DLPRewardDeployerImplementation.js.map +0 -1
  263. package/dist/generated/abi/DLPRewardDeployerTreasuryImplementation.cjs +0 -612
  264. package/dist/generated/abi/DLPRewardDeployerTreasuryImplementation.cjs.map +0 -1
  265. package/dist/generated/abi/DLPRewardDeployerTreasuryImplementation.d.ts +0 -451
  266. package/dist/generated/abi/DLPRewardDeployerTreasuryImplementation.js +0 -588
  267. package/dist/generated/abi/DLPRewardDeployerTreasuryImplementation.js.map +0 -1
  268. package/dist/generated/abi/DLPRewardSwapImplementation.cjs +0 -939
  269. package/dist/generated/abi/DLPRewardSwapImplementation.cjs.map +0 -1
  270. package/dist/generated/abi/DLPRewardSwapImplementation.d.ts +0 -705
  271. package/dist/generated/abi/DLPRewardSwapImplementation.js +0 -915
  272. package/dist/generated/abi/DLPRewardSwapImplementation.js.map +0 -1
  273. package/dist/generated/abi/DLPRootImplementation.cjs +0 -1644
  274. package/dist/generated/abi/DLPRootImplementation.cjs.map +0 -1
  275. package/dist/generated/abi/DLPRootImplementation.d.ts +0 -1246
  276. package/dist/generated/abi/DLPRootImplementation.js +0 -1620
  277. package/dist/generated/abi/DLPRootImplementation.js.map +0 -1
  278. package/dist/generated/abi/DataLiquidityPoolImplementation.cjs +0 -985
  279. package/dist/generated/abi/DataLiquidityPoolImplementation.cjs.map +0 -1
  280. package/dist/generated/abi/DataLiquidityPoolImplementation.d.ts +0 -735
  281. package/dist/generated/abi/DataLiquidityPoolImplementation.js +0 -961
  282. package/dist/generated/abi/DataLiquidityPoolImplementation.js.map +0 -1
  283. package/dist/generated/abi/SwapHelperImplementation.cjs +0 -976
  284. package/dist/generated/abi/SwapHelperImplementation.cjs.map +0 -1
  285. package/dist/generated/abi/SwapHelperImplementation.d.ts +0 -728
  286. package/dist/generated/abi/SwapHelperImplementation.js +0 -952
  287. package/dist/generated/abi/SwapHelperImplementation.js.map +0 -1
  288. package/dist/generated/abi/TeePoolImplementation.cjs +0 -1313
  289. package/dist/generated/abi/TeePoolImplementation.cjs.map +0 -1
  290. package/dist/generated/abi/TeePoolImplementation.d.ts +0 -992
  291. package/dist/generated/abi/TeePoolImplementation.js +0 -1289
  292. package/dist/generated/abi/TeePoolImplementation.js.map +0 -1
  293. package/dist/generated/event-types.cjs +0 -17
  294. package/dist/generated/event-types.cjs.map +0 -1
  295. package/dist/generated/event-types.d.ts +0 -809
  296. package/dist/generated/event-types.js +0 -1
  297. package/dist/generated/event-types.js.map +0 -1
  298. package/dist/generated/eventRegistry.cjs +0 -4470
  299. package/dist/generated/eventRegistry.cjs.map +0 -1
  300. package/dist/generated/eventRegistry.d.ts +0 -14
  301. package/dist/generated/eventRegistry.js +0 -4445
  302. package/dist/generated/eventRegistry.js.map +0 -1
  303. package/dist/generated/server/server-exports.cjs +0 -45
  304. package/dist/generated/server/server-exports.cjs.map +0 -1
  305. package/dist/generated/server/server-exports.d.ts +0 -36
  306. package/dist/generated/server/server-exports.js +0 -19
  307. package/dist/generated/server/server-exports.js.map +0 -1
  308. package/dist/generated/server/server.cjs +0 -17
  309. package/dist/generated/server/server.cjs.map +0 -1
  310. package/dist/generated/server/server.d.ts +0 -907
  311. package/dist/generated/server/server.js +0 -1
  312. package/dist/generated/server/server.js.map +0 -1
  313. package/dist/generated/subgraph.cjs +0 -1440
  314. package/dist/generated/subgraph.cjs.map +0 -1
  315. package/dist/generated/subgraph.d.ts +0 -6113
  316. package/dist/generated/subgraph.js +0 -1404
  317. package/dist/generated/subgraph.js.map +0 -1
  318. package/dist/lib/__tests__/redisAtomicStore.test.d.ts +0 -1
  319. package/dist/lib/redisAtomicStore.cjs +0 -201
  320. package/dist/lib/redisAtomicStore.cjs.map +0 -1
  321. package/dist/lib/redisAtomicStore.d.ts +0 -120
  322. package/dist/lib/redisAtomicStore.js +0 -177
  323. package/dist/lib/redisAtomicStore.js.map +0 -1
  324. package/dist/server/relayerHandler.cjs +0 -452
  325. package/dist/server/relayerHandler.cjs.map +0 -1
  326. package/dist/server/relayerHandler.d.ts +0 -69
  327. package/dist/server/relayerHandler.js +0 -428
  328. package/dist/server/relayerHandler.js.map +0 -1
  329. package/dist/tests/abi.test.d.ts +0 -1
  330. package/dist/tests/chains-definitions.test.d.ts +0 -1
  331. package/dist/tests/core-encryption.test.d.ts +0 -1
  332. package/dist/tests/core-extended.test.d.ts +0 -1
  333. package/dist/tests/core-generics-coverage.test.d.ts +0 -1
  334. package/dist/tests/coverage-boost.test.d.ts +0 -1
  335. package/dist/tests/crypto-cross-platform-compatibility.test.d.ts +0 -1
  336. package/dist/tests/data-addfile-permissions-schema.test.d.ts +0 -1
  337. package/dist/tests/data-additional-methods.test.d.ts +0 -1
  338. package/dist/tests/data-controller-edge-cases.test.d.ts +0 -1
  339. package/dist/tests/data-ipfs-gateways.test.d.ts +0 -1
  340. package/dist/tests/data-relayer.test.d.ts +0 -1
  341. package/dist/tests/data-schema-validation.test.d.ts +0 -1
  342. package/dist/tests/data-simple-methods.test.d.ts +0 -1
  343. package/dist/tests/data-upload-owner-validation.test.d.ts +0 -1
  344. package/dist/tests/data.test.d.ts +0 -1
  345. package/dist/tests/demo-integration.test.d.ts +0 -1
  346. package/dist/tests/demo-trusted-server-integration.test.d.ts +0 -1
  347. package/dist/tests/download-relayer.test.d.ts +0 -1
  348. package/dist/tests/dual-mode-permissions.test.d.ts +0 -1
  349. package/dist/tests/dual-mode-trusted-servers.test.d.ts +0 -1
  350. package/dist/tests/encryption-correct-implementation.test.d.ts +0 -1
  351. package/dist/tests/encryption-coverage.test.d.ts +0 -1
  352. package/dist/tests/encryption-edge-cases.test.d.ts +0 -1
  353. package/dist/tests/encryption-utils-updated.test.d.ts +0 -1
  354. package/dist/tests/errors-coverage.test.d.ts +0 -1
  355. package/dist/tests/factories/mockFactory.d.ts +0 -316
  356. package/dist/tests/fakes/FakeStorageManager.d.ts +0 -200
  357. package/dist/tests/fakes/FakeStorageManager.test.d.ts +0 -1
  358. package/dist/tests/fakes/FakeWaitForTransactionEvents.d.ts +0 -170
  359. package/dist/tests/fakes/FakeWaitForTransactionEvents.test.d.ts +0 -1
  360. package/dist/tests/fakes/fake-pgp-port.d.ts +0 -13
  361. package/dist/tests/grantValidation-edge-cases.test.d.ts +0 -1
  362. package/dist/tests/grantValidation-unreachable-branch.test.d.ts +0 -1
  363. package/dist/tests/helper-methods.test.d.ts +0 -1
  364. package/dist/tests/helpers/typedMocks.d.ts +0 -64
  365. package/dist/tests/index-browser.test.d.ts +0 -1
  366. package/dist/tests/index-node.test.d.ts +0 -1
  367. package/dist/tests/index.test.d.ts +0 -1
  368. package/dist/tests/mocks/platformAdapter.d.ts +0 -12
  369. package/dist/tests/new-permissions-methods.test.d.ts +0 -1
  370. package/dist/tests/no-buffer-browser.test.d.ts +0 -1
  371. package/dist/tests/permissions-grantee.test.d.ts +0 -1
  372. package/dist/tests/permissions-revoke-relayer.test.d.ts +0 -1
  373. package/dist/tests/permissions-schema-validation.test.d.ts +0 -1
  374. package/dist/tests/permissions-server-files.test.d.ts +0 -1
  375. package/dist/tests/permissions-transaction-options.test.d.ts +0 -1
  376. package/dist/tests/permissions-trust-servers.test.d.ts +0 -1
  377. package/dist/tests/permissions.test.d.ts +0 -1
  378. package/dist/tests/personal.test.d.ts +0 -1
  379. package/dist/tests/platform-browser.test.d.ts +0 -1
  380. package/dist/tests/platform-crypto-expanded.test.d.ts +0 -1
  381. package/dist/tests/platform-crypto.test.d.ts +0 -1
  382. package/dist/tests/platform-index.test.d.ts +0 -1
  383. package/dist/tests/platform-node.test.d.ts +0 -1
  384. package/dist/tests/platform-shared-utils.test.d.ts +0 -1
  385. package/dist/tests/platform-updated.test.d.ts +0 -1
  386. package/dist/tests/protocol-additional-methods.test.d.ts +0 -1
  387. package/dist/tests/protocol.test.d.ts +0 -1
  388. package/dist/tests/read-only-mode.test.d.ts +0 -1
  389. package/dist/tests/relayer-integration.test.d.ts +0 -1
  390. package/dist/tests/relayer-unified.test.d.ts +0 -1
  391. package/dist/tests/schemas.test.d.ts +0 -1
  392. package/dist/tests/server-relayer-handler.test.d.ts +0 -1
  393. package/dist/tests/signatureFormatter.test.d.ts +0 -1
  394. package/dist/tests/trusted-server-queries.test.d.ts +0 -1
  395. package/dist/tests/typedDataConverter.test.d.ts +0 -1
  396. package/dist/tests/types-contracts.test.d.ts +0 -1
  397. package/dist/tests/types-data.test.d.ts +0 -1
  398. package/dist/tests/types-external-apis.test.d.ts +0 -1
  399. package/dist/tests/types-generics.test.d.ts +0 -1
  400. package/dist/tests/types-permissions.test.d.ts +0 -1
  401. package/dist/tests/types-upload-params.test.d.ts +0 -1
  402. package/dist/tests/types.test.d.ts +0 -1
  403. package/dist/tests/utils-formatters.test.d.ts +0 -1
  404. package/dist/tests/utils-grantFiles-edge-cases.test.d.ts +0 -1
  405. package/dist/tests/utils-grantFiles-validation.test.d.ts +0 -1
  406. package/dist/tests/utils-grantFiles.test.d.ts +0 -1
  407. package/dist/tests/utils-grantValidation-consolidated.test.d.ts +0 -1
  408. package/dist/tests/utils-grants.test.d.ts +0 -1
  409. package/dist/tests/utils-ipfs-additional.test.d.ts +0 -1
  410. package/dist/tests/utils-ipfs.test.d.ts +0 -4
  411. package/dist/tests/utils-schemaValidation.test.d.ts +0 -1
  412. package/dist/tests/vana.test.d.ts +0 -1
  413. package/dist/tests/wallet-crypto-compatibility.test.d.ts +0 -1
  414. package/dist/types/atomicStore.cjs.map +0 -1
  415. package/dist/types/atomicStore.d.ts +0 -236
  416. package/dist/types/atomicStore.js +0 -7
  417. package/dist/types/atomicStore.js.map +0 -1
  418. package/dist/types/blockchain.cjs +0 -17
  419. package/dist/types/blockchain.cjs.map +0 -1
  420. package/dist/types/blockchain.d.ts +0 -85
  421. package/dist/types/blockchain.js +0 -1
  422. package/dist/types/blockchain.js.map +0 -1
  423. package/dist/types/controller-context.cjs +0 -17
  424. package/dist/types/controller-context.cjs.map +0 -1
  425. package/dist/types/controller-context.d.ts +0 -68
  426. package/dist/types/controller-context.js +0 -1
  427. package/dist/types/controller-context.js.map +0 -1
  428. package/dist/types/data.cjs +0 -17
  429. package/dist/types/data.cjs.map +0 -1
  430. package/dist/types/data.d.ts +0 -763
  431. package/dist/types/data.js +0 -1
  432. package/dist/types/data.js.map +0 -1
  433. package/dist/types/external-apis.cjs +0 -61
  434. package/dist/types/external-apis.cjs.map +0 -1
  435. package/dist/types/external-apis.d.ts +0 -184
  436. package/dist/types/external-apis.js +0 -34
  437. package/dist/types/external-apis.js.map +0 -1
  438. package/dist/types/generics.cjs +0 -17
  439. package/dist/types/generics.cjs.map +0 -1
  440. package/dist/types/generics.d.ts +0 -518
  441. package/dist/types/generics.js +0 -1
  442. package/dist/types/generics.js.map +0 -1
  443. package/dist/types/operationStore.cjs +0 -17
  444. package/dist/types/operationStore.cjs.map +0 -1
  445. package/dist/types/operationStore.d.ts +0 -171
  446. package/dist/types/operationStore.js +0 -1
  447. package/dist/types/operationStore.js.map +0 -1
  448. package/dist/types/operations.cjs +0 -53
  449. package/dist/types/operations.cjs.map +0 -1
  450. package/dist/types/operations.d.ts +0 -204
  451. package/dist/types/operations.js +0 -26
  452. package/dist/types/operations.js.map +0 -1
  453. package/dist/types/options.cjs +0 -17
  454. package/dist/types/options.cjs.map +0 -1
  455. package/dist/types/options.d.ts +0 -308
  456. package/dist/types/options.js +0 -1
  457. package/dist/types/options.js.map +0 -1
  458. package/dist/types/permissions.cjs +0 -17
  459. package/dist/types/permissions.cjs.map +0 -1
  460. package/dist/types/permissions.d.ts +0 -955
  461. package/dist/types/permissions.js +0 -1
  462. package/dist/types/permissions.js.map +0 -1
  463. package/dist/types/personal.cjs +0 -17
  464. package/dist/types/personal.cjs.map +0 -1
  465. package/dist/types/personal.d.ts +0 -174
  466. package/dist/types/personal.js +0 -1
  467. package/dist/types/personal.js.map +0 -1
  468. package/dist/types/relayer.cjs +0 -17
  469. package/dist/types/relayer.cjs.map +0 -1
  470. package/dist/types/relayer.d.ts +0 -552
  471. package/dist/types/relayer.js +0 -1
  472. package/dist/types/relayer.js.map +0 -1
  473. package/dist/types/transactionResults.cjs +0 -17
  474. package/dist/types/transactionResults.cjs.map +0 -1
  475. package/dist/types/transactionResults.d.ts +0 -193
  476. package/dist/types/transactionResults.js +0 -1
  477. package/dist/types/transactionResults.js.map +0 -1
  478. package/dist/types/utils.cjs +0 -17
  479. package/dist/types/utils.cjs.map +0 -1
  480. package/dist/types/utils.d.ts +0 -771
  481. package/dist/types/utils.js +0 -1
  482. package/dist/types/utils.js.map +0 -1
  483. package/dist/utils/__tests__/chainQuery.test.d.ts +0 -1
  484. package/dist/utils/__tests__/parseTransaction.test.d.ts +0 -1
  485. package/dist/utils/__tests__/pojo-serialization.test.d.ts +0 -1
  486. package/dist/utils/__tests__/signatureCache.test.d.ts +0 -1
  487. package/dist/utils/__tests__/subgraphConsistency.test.d.ts +0 -4
  488. package/dist/utils/__tests__/subgraphPagination.test.d.ts +0 -4
  489. package/dist/utils/__tests__/transaction-edge-cases.test.d.ts +0 -1
  490. package/dist/utils/__tests__/transactionHelpers.test.d.ts +0 -1
  491. package/dist/utils/__tests__/urlResolver.test.d.ts +0 -4
  492. package/dist/utils/blockchain/registry.cjs +0 -81
  493. package/dist/utils/blockchain/registry.cjs.map +0 -1
  494. package/dist/utils/blockchain/registry.d.ts +0 -32
  495. package/dist/utils/blockchain/registry.js +0 -56
  496. package/dist/utils/blockchain/registry.js.map +0 -1
  497. package/dist/utils/blockchain/registry.test.d.ts +0 -1
  498. package/dist/utils/chainQuery.cjs +0 -107
  499. package/dist/utils/chainQuery.cjs.map +0 -1
  500. package/dist/utils/chainQuery.d.ts +0 -31
  501. package/dist/utils/chainQuery.js +0 -82
  502. package/dist/utils/chainQuery.js.map +0 -1
  503. package/dist/utils/download.cjs +0 -69
  504. package/dist/utils/download.cjs.map +0 -1
  505. package/dist/utils/download.d.ts +0 -40
  506. package/dist/utils/download.js +0 -45
  507. package/dist/utils/download.js.map +0 -1
  508. package/dist/utils/encryption.cjs +0 -176
  509. package/dist/utils/encryption.cjs.map +0 -1
  510. package/dist/utils/encryption.d.ts +0 -271
  511. package/dist/utils/encryption.js +0 -142
  512. package/dist/utils/encryption.js.map +0 -1
  513. package/dist/utils/formatters.cjs +0 -55
  514. package/dist/utils/formatters.cjs.map +0 -1
  515. package/dist/utils/formatters.d.ts +0 -118
  516. package/dist/utils/formatters.js +0 -28
  517. package/dist/utils/formatters.js.map +0 -1
  518. package/dist/utils/grantFiles.cjs +0 -181
  519. package/dist/utils/grantFiles.cjs.map +0 -1
  520. package/dist/utils/grantFiles.d.ts +0 -172
  521. package/dist/utils/grantFiles.js +0 -143
  522. package/dist/utils/grantFiles.js.map +0 -1
  523. package/dist/utils/grantValidation.cjs +0 -243
  524. package/dist/utils/grantValidation.cjs.map +0 -1
  525. package/dist/utils/grantValidation.d.ts +0 -226
  526. package/dist/utils/grantValidation.js +0 -201
  527. package/dist/utils/grantValidation.js.map +0 -1
  528. package/dist/utils/grants.cjs +0 -108
  529. package/dist/utils/grants.cjs.map +0 -1
  530. package/dist/utils/grants.d.ts +0 -148
  531. package/dist/utils/grants.js +0 -82
  532. package/dist/utils/grants.js.map +0 -1
  533. package/dist/utils/ipfs.cjs +0 -128
  534. package/dist/utils/ipfs.cjs.map +0 -1
  535. package/dist/utils/ipfs.d.ts +0 -88
  536. package/dist/utils/ipfs.js +0 -97
  537. package/dist/utils/ipfs.js.map +0 -1
  538. package/dist/utils/multicall.cjs +0 -233
  539. package/dist/utils/multicall.cjs.map +0 -1
  540. package/dist/utils/multicall.d.ts +0 -126
  541. package/dist/utils/multicall.js +0 -208
  542. package/dist/utils/multicall.js.map +0 -1
  543. package/dist/utils/parseTransactionPojo.cjs +0 -87
  544. package/dist/utils/parseTransactionPojo.cjs.map +0 -1
  545. package/dist/utils/parseTransactionPojo.d.ts +0 -31
  546. package/dist/utils/parseTransactionPojo.js +0 -63
  547. package/dist/utils/parseTransactionPojo.js.map +0 -1
  548. package/dist/utils/schemaValidation.cjs +0 -258
  549. package/dist/utils/schemaValidation.cjs.map +0 -1
  550. package/dist/utils/schemaValidation.d.ts +0 -168
  551. package/dist/utils/schemaValidation.js +0 -219
  552. package/dist/utils/schemaValidation.js.map +0 -1
  553. package/dist/utils/signatureCache.cjs +0 -192
  554. package/dist/utils/signatureCache.cjs.map +0 -1
  555. package/dist/utils/signatureCache.d.ts +0 -172
  556. package/dist/utils/signatureCache.js +0 -167
  557. package/dist/utils/signatureCache.js.map +0 -1
  558. package/dist/utils/signatureFormatter.cjs +0 -42
  559. package/dist/utils/signatureFormatter.cjs.map +0 -1
  560. package/dist/utils/signatureFormatter.d.ts +0 -36
  561. package/dist/utils/signatureFormatter.js +0 -18
  562. package/dist/utils/signatureFormatter.js.map +0 -1
  563. package/dist/utils/subgraphConsistency.cjs +0 -184
  564. package/dist/utils/subgraphConsistency.cjs.map +0 -1
  565. package/dist/utils/subgraphConsistency.d.ts +0 -65
  566. package/dist/utils/subgraphConsistency.js +0 -155
  567. package/dist/utils/subgraphConsistency.js.map +0 -1
  568. package/dist/utils/subgraphMetaCache.cjs +0 -101
  569. package/dist/utils/subgraphMetaCache.cjs.map +0 -1
  570. package/dist/utils/subgraphMetaCache.d.ts +0 -56
  571. package/dist/utils/subgraphMetaCache.js +0 -76
  572. package/dist/utils/subgraphMetaCache.js.map +0 -1
  573. package/dist/utils/subgraphPagination.cjs +0 -104
  574. package/dist/utils/subgraphPagination.cjs.map +0 -1
  575. package/dist/utils/subgraphPagination.d.ts +0 -78
  576. package/dist/utils/subgraphPagination.js +0 -78
  577. package/dist/utils/subgraphPagination.js.map +0 -1
  578. package/dist/utils/tests/multicall.test.d.ts +0 -1
  579. package/dist/utils/transactionHelpers.cjs +0 -54
  580. package/dist/utils/transactionHelpers.cjs.map +0 -1
  581. package/dist/utils/transactionHelpers.d.ts +0 -80
  582. package/dist/utils/transactionHelpers.js +0 -29
  583. package/dist/utils/transactionHelpers.js.map +0 -1
  584. package/dist/utils/typeGuards.cjs +0 -109
  585. package/dist/utils/typeGuards.cjs.map +0 -1
  586. package/dist/utils/typeGuards.d.ts +0 -138
  587. package/dist/utils/typeGuards.js +0 -74
  588. package/dist/utils/typeGuards.js.map +0 -1
  589. package/dist/utils/typedDataConverter.cjs +0 -43
  590. package/dist/utils/typedDataConverter.cjs.map +0 -1
  591. package/dist/utils/typedDataConverter.d.ts +0 -46
  592. package/dist/utils/typedDataConverter.js +0 -19
  593. package/dist/utils/typedDataConverter.js.map +0 -1
  594. package/dist/utils/urlResolver.cjs +0 -62
  595. package/dist/utils/urlResolver.cjs.map +0 -1
  596. package/dist/utils/urlResolver.d.ts +0 -56
  597. package/dist/utils/urlResolver.js +0 -37
  598. package/dist/utils/urlResolver.js.map +0 -1
  599. package/dist/utils/wallet.cjs +0 -63
  600. package/dist/utils/wallet.cjs.map +0 -1
  601. package/dist/utils/wallet.d.ts +0 -94
  602. package/dist/utils/wallet.js +0 -37
  603. package/dist/utils/wallet.js.map +0 -1
  604. package/dist/utils/withEvents.cjs +0 -44
  605. package/dist/utils/withEvents.cjs.map +0 -1
  606. package/dist/utils/withEvents.d.ts +0 -56
  607. package/dist/utils/withEvents.js +0 -18
  608. package/dist/utils/withEvents.js.map +0 -1
  609. /package/dist/{__tests__/waitForTransactionEvents.test.d.ts → auth/pkce.test.d.ts} +0 -0
  610. /package/dist/{client/__tests__/enhancedResponse.test.d.ts → auth/token-store.test.d.ts} +0 -0
  611. /package/dist/{controllers/__tests__/operations.processQueue.test.d.ts → auth/web3-signed.test.d.ts} +0 -0
  612. /package/dist/{controllers/__tests__/schemas-edge-cases.test.d.ts → crypto/envelope/openpgp.test.d.ts} +0 -0
  613. /package/dist/{controllers/data-error-handling.test.d.ts → crypto/keys/derive.test.d.ts} +0 -0
  614. /package/dist/{tests/errors.test.d.ts → errors.test.d.ts} +0 -0
  615. /package/dist/{controllers/server-additional.test.d.ts → protocol/data-file.test.d.ts} +0 -0
  616. /package/dist/{core/__tests__/health.test.d.ts → protocol/eip712.test.d.ts} +0 -0
  617. /package/dist/{core/__tests__/inMemoryNonceManager.test.d.ts → protocol/gateway.test.d.ts} +0 -0
  618. /package/dist/{core/__tests__/nonceManager.test.d.ts → protocol/scopes.test.d.ts} +0 -0
  619. /package/dist/{core/core.test.d.ts → storage/tests/defaultStorage.test.d.ts} +0 -0
  620. /package/dist/{core/tests/apiClient.test.d.ts → storage/tests/r2Storage.test.d.ts} +0 -0
  621. /package/dist/{core/tests/client.test.d.ts → storage/tests/vanaStorage.test.d.ts} +0 -0
  622. /package/dist/{core/tests/generics.test.d.ts → types/ps-errors.test.d.ts} +0 -0
@@ -1,4344 +0,0 @@
1
- import { getAddress } from "viem";
2
- import { gasAwareMulticall } from "../utils/multicall";
3
- import { PollingManager } from "../core/pollingManager";
4
- import {
5
- RelayerError,
6
- UserRejectedRequestError,
7
- SerializationError,
8
- SignatureError,
9
- NetworkError,
10
- NonceError,
11
- BlockchainError,
12
- ServerUrlMismatchError,
13
- PermissionError
14
- } from "../errors";
15
- import { getContractAddress } from "../generated/addresses";
16
- import { getAbi } from "../generated/abi";
17
- import { createGrantFile, getGrantFileHash } from "../utils/grantFiles";
18
- import { validateGrant } from "../utils/grantValidation";
19
- import { withSignatureCache } from "../utils/signatureCache";
20
- import { formatSignatureForContract } from "../utils/signatureFormatter";
21
- import { toViemTypedDataDefinition } from "../utils/typedDataConverter";
22
- const MAX_UINT256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935n;
23
- import { BaseController } from "./base";
24
- class PermissionsController extends BaseController {
25
- constructor(context) {
26
- super(context);
27
- }
28
- /**
29
- * Grants permission for an application to access user data with gasless transactions.
30
- *
31
- * This method provides a complete end-to-end permission grant flow that returns
32
- * the permission ID and other relevant data immediately after successful submission.
33
- * For advanced users who need more control over the transaction lifecycle, use
34
- * `submitPermissionGrant()` instead.
35
- *
36
- * @param params - The permission grant configuration object
37
- * @returns Promise resolving to permission data from the PermissionAdded event
38
- * @throws {RelayerError} When gasless transaction submission fails
39
- * @throws {SignatureError} When user rejects the signature request
40
- * @throws {SerializationError} When grant data cannot be serialized
41
- * @throws {BlockchainError} When permission grant fails or event parsing fails
42
- * @throws {NetworkError} When transaction confirmation times out
43
- * @example
44
- * ```typescript
45
- * const result = await vana.permissions.grant({
46
- * grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
47
- * operation: "llm_inference",
48
- * parameters: {
49
- * model: "gpt-4",
50
- * maxTokens: 1000,
51
- * temperature: 0.7,
52
- * },
53
- * });
54
- *
55
- * console.log(`Permission ${result.permissionId} granted to ${result.user}`);
56
- * console.log(`Transaction: ${result.transactionHash}`);
57
- *
58
- * // Can immediately use the permission ID for other operations
59
- * await vana.permissions.revoke({ permissionId: result.permissionId });
60
- * ```
61
- */
62
- async grant(params, options) {
63
- this.assertWallet();
64
- const { typedData, signature } = await this.createAndSign(params);
65
- const result = await this.submitSignedGrantWithEvents(
66
- typedData,
67
- signature,
68
- options
69
- );
70
- return result;
71
- }
72
- /**
73
- * Submits a permission grant transaction and returns a handle for flexible result access.
74
- *
75
- * @remarks
76
- * This lower-level method provides maximum control over transaction timing.
77
- * Returns a TransactionResult that can be serialized and passed across API boundaries.
78
- * Use this when handling multiple transactions or when you need granular control.
79
- *
80
- * @param params - The permission grant configuration object
81
- * @returns Promise resolving to TransactionResult with hash and event parsing capabilities
82
- * @throws {RelayerError} When gasless transaction submission fails
83
- * @throws {SignatureError} When user rejects the signature request
84
- * @throws {SerializationError} When grant data cannot be serialized
85
- * @throws {BlockchainError} When permission grant preparation fails
86
- * @example
87
- * ```typescript
88
- * // Submit transaction and get immediate hash access
89
- * const tx = await vana.permissions.submitPermissionGrant(params);
90
- * console.log(`Transaction submitted: ${tx.hash}`);
91
- *
92
- * // To wait for events, use SDK's waitForTransactionEvents
93
- * const eventData = await vana.waitForTransactionEvents(tx.hash);
94
- * console.log(`Permission ID: ${eventData.permissionId}`);
95
- * ```
96
- */
97
- async submitPermissionGrant(params, options) {
98
- this.assertWallet();
99
- const { typedData, signature } = await this.createAndSign(params);
100
- return await this.submitSignedGrant(typedData, signature, options);
101
- }
102
- /**
103
- * Prepares a permission grant with preview before signing.
104
- *
105
- * @remarks
106
- * This method implements a two-phase commit workflow that allows applications
107
- * to show users a preview of what they're authorizing before requesting a signature.
108
- * Unlike `createAndSign()`, this method does NOT upload to IPFS or prompt for signatures
109
- * until the returned `confirm()` function is called.
110
- * @param params - The permission grant parameters
111
- * @returns A promise resolving to a preview object and confirm function
112
- * @throws {SerializationError} When grant parameters are invalid or cannot be serialized
113
- * @throws {BlockchainError} When grant validation fails or preparation encounters an error
114
- * @example
115
- * ```typescript
116
- * const { preview, confirm } = await vana.permissions.prepareGrant({
117
- * grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
118
- * operation: "llm_inference",
119
- * files: [1, 2, 3],
120
- * parameters: { model: "gpt-4", prompt: "Analyze my social media data" }
121
- * });
122
- *
123
- * console.log(`Granting ${preview.operation} access to ${preview.files?.length} files`);
124
- * const transactionHash = await confirm();
125
- * ```
126
- */
127
- async prepareGrant(params, options) {
128
- this.assertWallet();
129
- try {
130
- const grantFile = createGrantFile(params);
131
- validateGrant(grantFile);
132
- return {
133
- preview: grantFile,
134
- confirm: async () => {
135
- return await this.confirmGrantInternalWithEvents(
136
- params,
137
- grantFile,
138
- options
139
- );
140
- }
141
- };
142
- } catch (error) {
143
- if (error instanceof Error) {
144
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
145
- throw error;
146
- }
147
- throw new BlockchainError(
148
- `Permission grant preparation failed: ${error.message}`,
149
- error
150
- );
151
- }
152
- throw new BlockchainError(
153
- "Permission grant preparation failed with unknown error"
154
- );
155
- }
156
- }
157
- /**
158
- * Completes the grant process after user confirmation.
159
- *
160
- * @remarks
161
- * This internal method is called by the confirm() function returned from prepareGrant().
162
- * It handles IPFS upload, signature creation, and transaction submission.
163
- *
164
- * @param params - The permission grant parameters containing user and operation details
165
- * @param grantFile - The prepared grant file with permissions and metadata
166
- * @returns Promise resolving to TransactionResult for flexible result access
167
- * @throws {BlockchainError} When permission grant confirmation fails
168
- * @throws {NetworkError} When IPFS upload fails
169
- * @throws {SignatureError} When user rejects the signature
170
- */
171
- async confirmGrantInternal(params, grantFile, options) {
172
- try {
173
- let { grantUrl } = params;
174
- console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
175
- if (!grantUrl) {
176
- const canStoreViaRelayer = this.context.relayer !== void 0;
177
- if (!canStoreViaRelayer && !this.context.storageManager) {
178
- if (this.context.validateStorageRequired) {
179
- this.context.validateStorageRequired();
180
- } else {
181
- throw new Error(
182
- "No storage available. Provide a grantUrl, configure relayer, or storageManager."
183
- );
184
- }
185
- }
186
- if (canStoreViaRelayer && this.context.relayer) {
187
- const request = {
188
- type: "direct",
189
- operation: "storeGrantFile",
190
- params: grantFile
191
- };
192
- const response = await this.context.relayer(request);
193
- if (response.type === "error") {
194
- throw new Error(response.error);
195
- }
196
- if (response.type === "direct" && typeof response.result === "object" && response.result !== null && "url" in response.result) {
197
- grantUrl = response.result.url;
198
- } else {
199
- throw new Error("Invalid response from relayer for grant storage");
200
- }
201
- } else if (this.context.storageManager) {
202
- const blob = new Blob([JSON.stringify(grantFile)], {
203
- type: "application/json"
204
- });
205
- const result = await this.context.storageManager.upload(
206
- blob,
207
- `grant-${Date.now()}.json`
208
- );
209
- grantUrl = result.url;
210
- }
211
- if (!grantUrl) {
212
- throw new Error("Failed to store grant file - no URL returned");
213
- }
214
- }
215
- const nonce = await this.getPermissionsUserNonce();
216
- console.debug(
217
- "\u{1F50D} Debug - Final grant URL being passed to compose:",
218
- grantUrl
219
- );
220
- const typedData = await this.composePermissionGrantMessage({
221
- grantee: params.grantee,
222
- operation: params.operation,
223
- // Placeholder - real data is in IPFS
224
- files: params.files,
225
- // Placeholder - real data is in IPFS
226
- grantUrl,
227
- serializedParameters: getGrantFileHash(grantFile),
228
- // Hash as placeholder
229
- nonce
230
- });
231
- const signature = await this.signTypedData(typedData);
232
- return await this.submitSignedGrant(typedData, signature, options);
233
- } catch (error) {
234
- if (error instanceof Error) {
235
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
236
- throw error;
237
- }
238
- throw new BlockchainError(
239
- `Permission grant confirmation failed: ${error.message}`,
240
- error
241
- );
242
- }
243
- throw new BlockchainError(
244
- "Permission grant confirmation failed with unknown error"
245
- );
246
- }
247
- }
248
- /**
249
- * Creates typed data and signature for a permission grant without submitting.
250
- *
251
- * @remarks
252
- * This method handles the first phase of permission granting: creating the grant file,
253
- * storing it on IPFS, and generating the user's EIP-712 signature. Use this when you
254
- * want to handle submission separately or batch multiple operations. The method validates
255
- * the grant file against the JSON schema before creating the signature.
256
- *
257
- * For interactive user flows, consider using `prepareGrant()` instead,
258
- * which allows showing a preview before signing.
259
- * @param params - The permission grant configuration object
260
- * @returns A promise resolving to the typed data structure and signature for gasless submission
261
- * @throws {SignatureError} When the user rejects the signature request
262
- * @throws {SerializationError} When grant data cannot be properly formatted
263
- * @throws {BlockchainError} When permission grant preparation fails
264
- * @throws {NetworkError} When storage operations fail
265
- * @example
266
- * ```typescript
267
- * const { typedData, signature } = await vana.permissions.createAndSign({
268
- * grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
269
- * operation: "data_analysis",
270
- * parameters: { analysisType: "sentiment" },
271
- * });
272
- *
273
- * const transactionHash = await vana.permissions.submitSignedGrant(typedData, signature);
274
- * ```
275
- */
276
- async createAndSign(params) {
277
- this.assertWallet();
278
- try {
279
- const grantFile = createGrantFile(params);
280
- validateGrant(grantFile);
281
- let { grantUrl } = params;
282
- console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
283
- if (!grantUrl) {
284
- const canStoreViaRelayer = this.context.relayer !== void 0;
285
- if (!canStoreViaRelayer && !this.context.storageManager) {
286
- if (this.context.validateStorageRequired) {
287
- this.context.validateStorageRequired();
288
- } else {
289
- throw new Error(
290
- "No storage available. Provide a grantUrl, configure relayer, or storageManager."
291
- );
292
- }
293
- }
294
- if (canStoreViaRelayer && this.context.relayer) {
295
- const request = {
296
- type: "direct",
297
- operation: "storeGrantFile",
298
- params: grantFile
299
- };
300
- const response = await this.context.relayer(request);
301
- if (response.type === "error") {
302
- throw new Error(response.error);
303
- }
304
- if (response.type === "direct" && typeof response.result === "object" && response.result !== null && "url" in response.result) {
305
- grantUrl = response.result.url;
306
- } else {
307
- throw new Error("Invalid response from relayer for grant storage");
308
- }
309
- } else if (this.context.storageManager) {
310
- const blob = new Blob([JSON.stringify(grantFile)], {
311
- type: "application/json"
312
- });
313
- const result = await this.context.storageManager.upload(
314
- blob,
315
- `grant-${Date.now()}.json`
316
- );
317
- grantUrl = result.url;
318
- }
319
- if (!grantUrl) {
320
- throw new Error("Failed to store grant file - no URL returned");
321
- }
322
- }
323
- const nonce = await this.getPermissionsUserNonce();
324
- console.debug(
325
- "\u{1F50D} Debug - Final grant URL being passed to compose:",
326
- grantUrl
327
- );
328
- const typedData = await this.composePermissionGrantMessage({
329
- grantee: params.grantee,
330
- operation: params.operation,
331
- // Placeholder - real data is in IPFS
332
- files: params.files,
333
- // Placeholder - real data is in IPFS
334
- grantUrl,
335
- serializedParameters: getGrantFileHash(grantFile),
336
- // Hash as placeholder
337
- nonce
338
- });
339
- const signature = await this.signTypedData(typedData);
340
- return { typedData, signature };
341
- } catch (error) {
342
- if (error instanceof Error) {
343
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
344
- throw error;
345
- }
346
- throw new BlockchainError(
347
- `Permission grant preparation failed: ${error.message}`,
348
- error
349
- );
350
- }
351
- throw new BlockchainError(
352
- "Permission grant preparation failed with unknown error"
353
- );
354
- }
355
- }
356
- /**
357
- * Submits an already-signed permission grant to the blockchain.
358
- *
359
- * @remarks
360
- * This method supports both relayer-based gasless transactions and direct transactions.
361
- * It automatically converts `bigint` values to JSON-safe strings when using relayer
362
- * callbacks and handles transaction submission with proper error handling and retry logic.
363
- * @param typedData - The EIP-712 typed data structure for the permission grant
364
- * @param signature - The user's signature as a hex string
365
- * @returns A Promise that resolves to the transaction hash
366
- * @throws {RelayerError} When gasless transaction submission fails
367
- * @throws {BlockchainError} When permission submission fails
368
- * @throws {NetworkError} When network communication fails
369
- * @example
370
- * ```typescript
371
- * const txHash = await vana.permissions.submitSignedGrant(
372
- * typedData,
373
- * "0x1234..."
374
- * );
375
- * ```
376
- */
377
- async submitSignedGrant(typedData, signature, options) {
378
- try {
379
- console.debug(
380
- "\u{1F50D} Debug - submitSignedGrant called with typed data:",
381
- JSON.stringify(
382
- typedData,
383
- (_key, value) => typeof value === "bigint" ? value.toString() : value,
384
- 2
385
- )
386
- );
387
- if (this.context.relayer) {
388
- const response = await this.context.relayer({
389
- type: "signed",
390
- operation: "submitAddPermission",
391
- typedData,
392
- signature,
393
- expectedUserAddress: this.context.userAddress
394
- });
395
- if (response.type === "error") {
396
- throw new Error(`Relayer error: ${response.error}`);
397
- }
398
- let finalHash;
399
- if (response.type === "submitted") {
400
- finalHash = response.hash;
401
- } else if (response.type === "pending") {
402
- const pollResult = await this.pollRelayerForConfirmation(
403
- response.operationId,
404
- options
405
- );
406
- finalHash = pollResult.hash;
407
- } else if (response.type === "confirmed") {
408
- finalHash = response.hash;
409
- } else if (response.type === "signed") {
410
- finalHash = response.hash;
411
- } else {
412
- throw new Error(
413
- "Invalid response from relayer: unexpected response type"
414
- );
415
- }
416
- const account = this.context.walletClient?.account ?? this.context.userAddress;
417
- const { tx } = await import("../utils/transactionHelpers");
418
- return tx({
419
- hash: finalHash,
420
- from: typeof account === "string" ? account : account.address,
421
- contract: "DataPortabilityPermissions",
422
- fn: "addPermission"
423
- });
424
- } else {
425
- return await this.submitDirectTransaction(
426
- typedData,
427
- signature,
428
- options
429
- );
430
- }
431
- } catch (error) {
432
- if (error instanceof RelayerError || error instanceof NetworkError || error instanceof UserRejectedRequestError || error instanceof SignatureError || error instanceof NonceError) {
433
- throw error;
434
- }
435
- throw new BlockchainError(
436
- `Permission submission failed: ${error instanceof Error ? error.message : "Unknown error"}`,
437
- error
438
- );
439
- }
440
- }
441
- /**
442
- * Submits an already-signed trust server transaction to the blockchain.
443
- *
444
- * @remarks
445
- * This method extracts the trust server input from typed data and submits it directly.
446
- * Used internally by trust server methods after signature collection.
447
- *
448
- * @param typedData - The EIP-712 typed data for TrustServer
449
- * @param signature - The user's signature obtained via `signTypedData()`
450
- * @returns Promise resolving to TransactionResult for transaction tracking
451
- * @throws {BlockchainError} When contract submission fails
452
- * @throws {NetworkError} When blockchain communication fails
453
- * @example
454
- * ```typescript
455
- * const txHandle = await vana.permissions.submitSignedTrustServer(
456
- * typedData,
457
- * "0x1234..."
458
- * );
459
- * const result = await txHandle.waitForEvents();
460
- * ```
461
- */
462
- async submitSignedTrustServer(typedData, signature, options) {
463
- try {
464
- const trustServerInput = {
465
- nonce: BigInt(typedData.message.nonce),
466
- serverId: typedData.message.serverId
467
- };
468
- const hash = await this.submitTrustServerTransaction(
469
- trustServerInput,
470
- signature,
471
- options
472
- );
473
- const account = this.context.userAddress;
474
- const { tx } = await import("../utils/transactionHelpers");
475
- return tx({
476
- hash,
477
- from: account,
478
- contract: "DataPortabilityServers",
479
- fn: "trustServerWithSignature"
480
- });
481
- } catch (error) {
482
- if (error instanceof RelayerError || error instanceof NetworkError || error instanceof UserRejectedRequestError || error instanceof SignatureError || error instanceof NonceError) {
483
- throw error;
484
- }
485
- if (error instanceof Error && error.message.includes("ServerUrlMismatch")) {
486
- const match = error.message.match(
487
- /ServerUrlMismatch\(string existingUrl, string providedUrl\)\s+\(([^,]+),\s*([^)]+)\)/
488
- );
489
- if (match) {
490
- const existingUrl = match[1].trim();
491
- const providedUrl = match[2].trim();
492
- throw new ServerUrlMismatchError(
493
- existingUrl,
494
- providedUrl,
495
- typedData.message.serverId.toString()
496
- );
497
- }
498
- }
499
- throw new BlockchainError(
500
- `Trust server submission failed: ${error instanceof Error ? error.message : "Unknown error"}`,
501
- error
502
- );
503
- }
504
- }
505
- /**
506
- * Submits an already-signed add and trust server transaction to the blockchain.
507
- *
508
- * @remarks
509
- * This method extracts the add and trust server input from typed data and submits it directly.
510
- * Combines server registration and trust operations in a single transaction.
511
- *
512
- * @param typedData - The EIP-712 typed data for AddAndTrustServer
513
- * @param signature - The user's signature obtained via `signTypedData()`
514
- * @returns Promise resolving to TransactionResult for transaction tracking
515
- * @throws {BlockchainError} When contract submission fails
516
- * @throws {NetworkError} When blockchain communication fails
517
- * @example
518
- * ```typescript
519
- * const txHandle = await vana.permissions.submitSignedAddAndTrustServer(
520
- * typedData,
521
- * "0x1234..."
522
- * );
523
- * const result = await txHandle.waitForEvents();
524
- * ```
525
- */
526
- async submitSignedAddAndTrustServer(typedData, signature, options) {
527
- try {
528
- const addAndTrustServerInput = {
529
- nonce: BigInt(typedData.message.nonce),
530
- serverAddress: typedData.message.serverAddress,
531
- serverUrl: typedData.message.serverUrl,
532
- publicKey: typedData.message.publicKey
533
- };
534
- const hash = await this.submitAddAndTrustServerTransaction(
535
- addAndTrustServerInput,
536
- signature,
537
- options
538
- );
539
- const account = this.context.walletClient?.account ?? this.context.userAddress;
540
- const { tx } = await import("../utils/transactionHelpers");
541
- return tx({
542
- hash,
543
- from: typeof account === "string" ? account : account.address,
544
- contract: "DataPortabilityServers",
545
- fn: "addAndTrustServerWithSignature"
546
- });
547
- } catch (error) {
548
- if (error instanceof RelayerError || error instanceof NetworkError || error instanceof UserRejectedRequestError || error instanceof SignatureError || error instanceof NonceError) {
549
- throw error;
550
- }
551
- throw new BlockchainError(
552
- `Add and trust server submission failed444444: ${error instanceof Error ? error.message : "Unknown error"}`,
553
- error
554
- );
555
- }
556
- }
557
- /**
558
- * Internal method to submit a signed grant and wait for events.
559
- *
560
- * @internal
561
- * @param typedData - The EIP-712 typed data for the permission grant
562
- * @param signature - The user's signature authorizing the transaction
563
- * @returns Promise resolving to PermissionGrantResult with parsed events
564
- */
565
- async submitSignedGrantWithEvents(typedData, signature, options) {
566
- const txResult = await this.submitSignedGrant(
567
- typedData,
568
- signature,
569
- options
570
- );
571
- if (!this.context.waitForTransactionEvents) {
572
- throw new BlockchainError("waitForTransactionEvents not configured");
573
- }
574
- const result = await this.context.waitForTransactionEvents(txResult);
575
- const event = result.expectedEvents.PermissionAdded;
576
- if (!event) {
577
- throw new BlockchainError(
578
- "PermissionAdded event not found in transaction"
579
- );
580
- }
581
- const receipt = await this.context.publicClient.getTransactionReceipt({
582
- hash: result.hash
583
- });
584
- return {
585
- transactionHash: result.hash,
586
- blockNumber: receipt.blockNumber,
587
- gasUsed: receipt.gasUsed,
588
- permissionId: event.permissionId,
589
- user: event.user,
590
- grant: event.grant,
591
- fileIds: event.fileIds
592
- };
593
- }
594
- /**
595
- * Internal method for confirm grant with events.
596
- *
597
- * @internal
598
- * @param params - The permission grant parameters
599
- * @param grantFile - The pre-created grant file object
600
- * @returns Promise resolving to PermissionGrantResult with parsed events
601
- */
602
- async confirmGrantInternalWithEvents(params, grantFile, options) {
603
- const txResult = await this.confirmGrantInternal(
604
- params,
605
- grantFile,
606
- options
607
- );
608
- if (!this.context.waitForTransactionEvents) {
609
- throw new BlockchainError("waitForTransactionEvents not configured");
610
- }
611
- const result = await this.context.waitForTransactionEvents(txResult);
612
- const event = result.expectedEvents.PermissionAdded;
613
- if (!event) {
614
- throw new BlockchainError(
615
- "PermissionAdded event not found in transaction"
616
- );
617
- }
618
- const receipt = await this.context.publicClient.getTransactionReceipt({
619
- hash: result.hash
620
- });
621
- return {
622
- transactionHash: result.hash,
623
- blockNumber: receipt.blockNumber,
624
- gasUsed: receipt.gasUsed,
625
- permissionId: event.permissionId,
626
- user: event.user,
627
- grant: event.grant,
628
- fileIds: event.fileIds
629
- };
630
- }
631
- /**
632
- * Polls the relayer for confirmation of a pending operation.
633
- *
634
- * @param operationId - The operation ID to poll
635
- * @param options - Polling configuration including status updates and cancellation
636
- * @returns Promise resolving to the confirmed hash and receipt
637
- * @throws {TransactionPendingError} When the operation times out
638
- * @throws {Error} When the operation fails or is cancelled
639
- * @internal
640
- */
641
- async pollRelayerForConfirmation(operationId, options) {
642
- if (!this.context.relayer) {
643
- throw new Error("Relayer not configured for polling");
644
- }
645
- const pollingManager = new PollingManager(this.context.relayer);
646
- return await pollingManager.startPolling(operationId, {
647
- signal: options?.signal,
648
- onStatusUpdate: options?.onStatusUpdate,
649
- ...options?.pollingOptions
650
- });
651
- }
652
- /**
653
- * Submits an already-signed permission revoke transaction to the blockchain.
654
- *
655
- * @remarks
656
- * This method handles the revocation of previously granted permissions.
657
- * Used internally by revocation methods after signature collection.
658
- *
659
- * @param typedData - The EIP-712 typed data for PermissionRevoke
660
- * @param signature - The user's signature obtained via `signTypedData()`
661
- * @returns Promise resolving to TransactionResult for transaction tracking
662
- * @throws {BlockchainError} When contract submission fails
663
- * @throws {NetworkError} When blockchain communication fails
664
- * @example
665
- * ```typescript
666
- * const txHandle = await vana.permissions.submitSignedRevoke(
667
- * typedData,
668
- * "0x1234..."
669
- * );
670
- * const result = await txHandle.waitForEvents();
671
- * ```
672
- */
673
- async submitSignedRevoke(typedData, signature, options) {
674
- try {
675
- let hash;
676
- if (this.context.relayer) {
677
- const response = await this.context.relayer({
678
- type: "signed",
679
- operation: "submitPermissionRevoke",
680
- typedData,
681
- signature,
682
- expectedUserAddress: this.context.userAddress
683
- });
684
- if (response.type === "error") {
685
- throw new Error(`Relayer error: ${response.error}`);
686
- }
687
- if (response.type === "submitted") {
688
- hash = response.hash;
689
- } else if (response.type === "pending") {
690
- const pollResult = await this.pollRelayerForConfirmation(
691
- response.operationId,
692
- options
693
- );
694
- hash = pollResult.hash;
695
- } else if (response.type === "confirmed") {
696
- hash = response.hash;
697
- } else if (response.type === "signed") {
698
- hash = response.hash;
699
- } else {
700
- throw new Error(
701
- "Invalid response from relayer: unexpected response type"
702
- );
703
- }
704
- } else {
705
- hash = await this.submitDirectRevokeTransaction(
706
- typedData,
707
- signature,
708
- options
709
- );
710
- }
711
- const account = this.context.walletClient?.account ?? this.context.userAddress;
712
- const { tx } = await import("../utils/transactionHelpers");
713
- return tx({
714
- hash,
715
- from: typeof account === "string" ? account : account.address,
716
- contract: "DataPortabilityPermissions",
717
- fn: "revokePermissionWithSignature"
718
- });
719
- } catch (error) {
720
- if (error instanceof RelayerError || error instanceof NetworkError || error instanceof UserRejectedRequestError || error instanceof SignatureError || error instanceof NonceError) {
721
- throw error;
722
- }
723
- throw new BlockchainError(
724
- `Permission revoke submission failed: ${error instanceof Error ? error.message : "Unknown error"}`,
725
- error
726
- );
727
- }
728
- }
729
- /**
730
- * Submits an already-signed untrust server transaction to the blockchain.
731
- *
732
- * @remarks
733
- * This method handles the removal of trusted servers.
734
- * Used internally by untrust server methods after signature collection.
735
- *
736
- * @param typedData - The EIP-712 typed data for UntrustServer
737
- * @param signature - The user's signature obtained via `signTypedData()`
738
- * @returns Promise resolving to TransactionResult for transaction tracking
739
- * @throws {BlockchainError} When contract submission fails
740
- * @throws {NetworkError} When blockchain communication fails
741
- * @example
742
- * ```typescript
743
- * const txHandle = await vana.permissions.submitSignedUntrustServer(
744
- * typedData,
745
- * "0x1234..."
746
- * );
747
- * const result = await txHandle.waitForEvents();
748
- * ```
749
- */
750
- async submitSignedUntrustServer(typedData, signature, options) {
751
- try {
752
- let hash;
753
- if (this.context.relayer) {
754
- const response = await this.context.relayer({
755
- type: "signed",
756
- operation: "submitUntrustServer",
757
- typedData,
758
- signature,
759
- expectedUserAddress: this.context.userAddress
760
- });
761
- if (response.type === "submitted") {
762
- hash = response.hash;
763
- } else if (response.type === "signed") {
764
- hash = response.hash;
765
- } else if (response.type === "error") {
766
- throw new Error(`Relayer error: ${response.error}`);
767
- } else {
768
- throw new Error(
769
- "Invalid response from relayer: expected signed transaction"
770
- );
771
- }
772
- } else {
773
- hash = await this.submitSignedUntrustTransaction(
774
- typedData,
775
- signature,
776
- options
777
- );
778
- }
779
- const account = this.context.walletClient?.account ?? this.context.userAddress;
780
- const { tx } = await import("../utils/transactionHelpers");
781
- return tx({
782
- hash,
783
- from: typeof account === "string" ? account : account.address,
784
- contract: "DataPortabilityServers",
785
- fn: "untrustServerWithSignature"
786
- });
787
- } catch (error) {
788
- if (error instanceof RelayerError || error instanceof NetworkError || error instanceof UserRejectedRequestError || error instanceof SignatureError || error instanceof NonceError) {
789
- throw error;
790
- }
791
- throw new BlockchainError(
792
- `Untrust server submission failed: ${error instanceof Error ? error.message : "Unknown error"}`,
793
- error
794
- );
795
- }
796
- }
797
- /**
798
- * Submits a signed transaction directly to the blockchain.
799
- *
800
- * @remarks
801
- * Internal method used when relayer callbacks are not available. Formats the signature
802
- * and submits the permission grant directly to the smart contract.
803
- *
804
- * @param typedData - The typed data structure for the permission grant
805
- * @param signature - The cryptographic signature authorizing the transaction
806
- * @returns Promise resolving to the transaction hash
807
- * @throws {BlockchainError} When contract submission fails
808
- */
809
- async submitDirectTransaction(typedData, signature, options) {
810
- this.assertWallet();
811
- const chainId = await this.context.publicClient.getChainId();
812
- const DataPortabilityPermissionsAddress = getContractAddress(
813
- chainId,
814
- "DataPortabilityPermissions"
815
- );
816
- const DataPortabilityPermissionsAbi = getAbi("DataPortabilityPermissions");
817
- const permissionInput = {
818
- nonce: typedData.message.nonce,
819
- granteeId: typedData.message.granteeId,
820
- grant: typedData.message.grant,
821
- fileIds: typedData.message.fileIds
822
- };
823
- console.debug("\u{1F50D} Debug - Permission input being sent to contract:", {
824
- nonce: permissionInput.nonce.toString(),
825
- grant: permissionInput.grant,
826
- fileIds: permissionInput.fileIds.map((id) => id.toString())
827
- });
828
- console.debug("\u{1F50D} Debug - Grant field value:", typedData.message.grant);
829
- console.debug(
830
- "\u{1F50D} Debug - Grant field length:",
831
- typedData.message.grant?.length ?? 0
832
- );
833
- const formattedSignature = formatSignatureForContract(signature);
834
- const account = this.context.walletClient?.account ?? this.context.userAddress;
835
- const txHash = await this.context.walletClient.writeContract({
836
- address: DataPortabilityPermissionsAddress,
837
- abi: DataPortabilityPermissionsAbi,
838
- functionName: "addPermission",
839
- args: [permissionInput, formattedSignature],
840
- account,
841
- chain: this.context.walletClient?.chain ?? null,
842
- ...this.spreadTransactionOptions(options)
843
- });
844
- const { tx } = await import("../utils/transactionHelpers");
845
- return tx({
846
- hash: txHash,
847
- from: typeof account === "string" ? account : account.address,
848
- contract: "DataPortabilityPermissions",
849
- fn: "addPermission"
850
- });
851
- }
852
- /**
853
- * Revokes a previously granted permission.
854
- *
855
- * This method provides complete revocation with automatic event parsing to confirm
856
- * the permission was successfully revoked. For advanced users who need more control,
857
- * use `submitPermissionRevoke()` instead.
858
- *
859
- * @param params - Parameters for revoking the permission
860
- * @param params.permissionId - Permission identifier (accepts bigint, number, or string).
861
- * Obtain from permission grants via `getUserPermissionGrantsOnChain()`.
862
- * @returns Promise resolving to revocation data from PermissionRevoked event
863
- * @throws {BlockchainError} When revocation fails or event parsing fails
864
- * @throws {UserRejectedRequestError} When user rejects the transaction
865
- * @throws {NetworkError} When transaction confirmation times out
866
- * @example
867
- * ```typescript
868
- * // Revoke a permission and get confirmation
869
- * const result = await vana.permissions.revoke({
870
- * permissionId: 123n
871
- * });
872
- * console.log(`Permission ${result.permissionId} revoked in transaction ${result.transactionHash}`);
873
- * console.log(`Revoked in block ${result.blockNumber}`);
874
- * ```
875
- */
876
- async revoke(params) {
877
- this.assertWallet();
878
- const txResult = await this.submitPermissionRevoke(params);
879
- if (!this.context.waitForTransactionEvents) {
880
- throw new BlockchainError("waitForTransactionEvents not configured");
881
- }
882
- const result = await this.context.waitForTransactionEvents(txResult);
883
- const event = result.expectedEvents.PermissionRevoked;
884
- if (!event) {
885
- throw new BlockchainError(
886
- "PermissionRevoked event not found in transaction"
887
- );
888
- }
889
- const receipt = await this.context.publicClient.getTransactionReceipt({
890
- hash: result.hash
891
- });
892
- return {
893
- transactionHash: result.hash,
894
- blockNumber: receipt.blockNumber,
895
- gasUsed: receipt.gasUsed,
896
- permissionId: event.permissionId
897
- };
898
- }
899
- /**
900
- * Submits a permission revocation transaction and returns the transaction hash immediately.
901
- *
902
- * This is the lower-level method that provides maximum control over transaction timing.
903
- * Use this when you want to handle transaction confirmation and event parsing separately.
904
- *
905
- * @param params - Parameters for revoking the permission
906
- * @param options - Optional transaction options for gas parameters and timeout
907
- * @returns Promise resolving to the transaction hash when successfully submitted
908
- * @throws {BlockchainError} When revocation transaction fails
909
- * @throws {UserRejectedRequestError} When user rejects the transaction
910
- * @example
911
- * ```typescript
912
- * // Submit revocation and handle confirmation later
913
- * const txHash = await vana.permissions.submitPermissionRevoke({
914
- * permissionId: 123n
915
- * });
916
- * console.log(`Revocation submitted: ${txHash}`);
917
- * ```
918
- */
919
- async submitPermissionRevoke(params, options) {
920
- this.assertWallet();
921
- try {
922
- if (!this.context.walletClient?.chain?.id) {
923
- throw new BlockchainError("Chain ID not available");
924
- }
925
- const chainId = await this.context.publicClient.getChainId();
926
- const DataPortabilityPermissionsAddress = getContractAddress(
927
- chainId,
928
- "DataPortabilityPermissions"
929
- );
930
- const DataPortabilityPermissionsAbi = getAbi(
931
- "DataPortabilityPermissions"
932
- );
933
- const account = this.context.walletClient?.account ?? this.context.userAddress;
934
- const txHash = await this.context.walletClient.writeContract({
935
- address: DataPortabilityPermissionsAddress,
936
- abi: DataPortabilityPermissionsAbi,
937
- functionName: "revokePermission",
938
- args: [params.permissionId],
939
- account,
940
- chain: this.context.walletClient?.chain ?? null,
941
- ...options?.gas && { gas: options.gas },
942
- ...options?.nonce && { nonce: options.nonce },
943
- // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
944
- ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
945
- ...options.maxFeePerGas && {
946
- maxFeePerGas: options.maxFeePerGas
947
- },
948
- ...options.maxPriorityFeePerGas && {
949
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
950
- }
951
- } : options?.gasPrice && { gasPrice: options.gasPrice }
952
- });
953
- const { tx } = await import("../utils/transactionHelpers");
954
- return tx({
955
- hash: txHash,
956
- from: typeof account === "string" ? account : account.address,
957
- contract: "DataPortabilityPermissions",
958
- fn: "revokePermission"
959
- });
960
- } catch (error) {
961
- if (error instanceof Error) {
962
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
963
- throw error;
964
- }
965
- throw new BlockchainError(
966
- `Permission revoke failed: ${error.message}`,
967
- error
968
- );
969
- }
970
- throw new BlockchainError("Permission revoke failed with unknown error");
971
- }
972
- }
973
- /**
974
- * Revokes a permission with a signature for gasless transactions.
975
- *
976
- * @remarks
977
- * This method creates an EIP-712 signature for permission revocation and submits
978
- * it either through relayer callbacks or directly to the blockchain. Provides
979
- * gasless revocation when relayer is configured.
980
- *
981
- * @param params - Parameters for revoking the permission
982
- * @param params.permissionId - Permission identifier to revoke (accepts bigint, number, or string)
983
- * @returns Promise resolving to TransactionResult for transaction tracking
984
- * @throws {BlockchainError} When chain ID is not available
985
- * @throws {NonceError} When retrieving user nonce fails
986
- * @throws {SignatureError} When user rejects the signature request
987
- * @throws {RelayerError} When gasless submission fails
988
- * @throws {PermissionError} When revocation fails for any other reason
989
- * @example
990
- * ```typescript
991
- * const txHandle = await vana.permissions.submitRevokeWithSignature({
992
- * permissionId: 123n
993
- * });
994
- * const result = await txHandle.waitForEvents();
995
- * console.log(`Permission ${result.permissionId} revoked`);
996
- * ```
997
- */
998
- async submitRevokeWithSignature(params, options) {
999
- this.assertWallet();
1000
- try {
1001
- if (!this.context.walletClient?.chain?.id) {
1002
- throw new BlockchainError("Chain ID not available");
1003
- }
1004
- const nonce = await this.getPermissionsUserNonce();
1005
- const revokePermissionInput = {
1006
- nonce,
1007
- permissionId: params.permissionId
1008
- };
1009
- const typedData = {
1010
- domain: await this.getPermissionDomain(),
1011
- types: {
1012
- RevokePermission: [
1013
- { name: "nonce", type: "uint256" },
1014
- { name: "permissionId", type: "uint256" }
1015
- ]
1016
- },
1017
- primaryType: "RevokePermission",
1018
- message: revokePermissionInput
1019
- };
1020
- const signature = await this.signTypedData(typedData);
1021
- let hash;
1022
- if (this.context.relayer) {
1023
- const response = await this.context.relayer({
1024
- type: "signed",
1025
- operation: "submitPermissionRevoke",
1026
- typedData,
1027
- signature,
1028
- expectedUserAddress: this.context.userAddress
1029
- });
1030
- if (response.type === "submitted") {
1031
- hash = response.hash;
1032
- } else if (response.type === "signed") {
1033
- hash = response.hash;
1034
- } else if (response.type === "error") {
1035
- throw new Error(`Relayer error: ${response.error}`);
1036
- } else {
1037
- throw new Error(
1038
- "Invalid response from relayer: expected signed transaction"
1039
- );
1040
- }
1041
- } else {
1042
- hash = await this.submitDirectRevokeTransaction(
1043
- typedData,
1044
- signature,
1045
- options
1046
- );
1047
- }
1048
- const account = this.context.walletClient?.account ?? this.context.userAddress;
1049
- const { tx } = await import("../utils/transactionHelpers");
1050
- return tx({
1051
- hash,
1052
- from: typeof account === "string" ? account : account.address,
1053
- contract: "DataPortabilityPermissions",
1054
- fn: "revokePermissionWithSignature"
1055
- });
1056
- } catch (error) {
1057
- throw new PermissionError(
1058
- `Failed to revoke permission with signature: ${error instanceof Error ? error.message : "Unknown error"}`,
1059
- error
1060
- );
1061
- }
1062
- }
1063
- /**
1064
- * Retrieves the user's current nonce from the DataPortabilityServers contract.
1065
- * This nonce is used for server-related operations (AddAndTrustServer, TrustServer, UntrustServer).
1066
- *
1067
- * @returns Promise resolving to the current servers nonce
1068
- * @throws {NonceError} When reading nonce from contract fails
1069
- * @private
1070
- *
1071
- * @example
1072
- * ```typescript
1073
- * const nonce = await this.getServersUserNonce();
1074
- * console.log(`Current servers nonce: ${nonce}`);
1075
- * ```
1076
- */
1077
- /**
1078
- * Retrieves the user's current nonce from the DataPortabilityServers contract.
1079
- *
1080
- * @remarks
1081
- * Used for server-related operations (trust/untrust) to prevent replay attacks.
1082
- * The nonce must be incremented with each server operation.
1083
- *
1084
- * @returns Promise resolving to the user's current nonce as a bigint
1085
- * @throws {NonceError} When retrieving the nonce fails
1086
- */
1087
- async getServersUserNonce() {
1088
- try {
1089
- const userAddress = this.context.userAddress;
1090
- const chainId = await this.context.publicClient.getChainId();
1091
- const DataPortabilityServersAddress = getContractAddress(
1092
- chainId,
1093
- "DataPortabilityServers"
1094
- );
1095
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
1096
- const [nonce] = await this.context.publicClient.readContract({
1097
- address: DataPortabilityServersAddress,
1098
- abi: DataPortabilityServersAbi,
1099
- functionName: "users",
1100
- args: [userAddress]
1101
- });
1102
- return nonce;
1103
- } catch (error) {
1104
- throw new NonceError(
1105
- `Failed to retrieve server nonce: ${error instanceof Error ? error.message : "Unknown error"}`
1106
- );
1107
- }
1108
- }
1109
- /**
1110
- * Retrieves the user's current nonce from the DataPortabilityPermissions contract.
1111
- * This nonce is used for permission-related operations (addPermission, addServerFilesAndPermissions).
1112
- *
1113
- * @returns Promise resolving to the current permissions nonce
1114
- * @throws {NonceError} When reading nonce from contract fails
1115
- * @private
1116
- *
1117
- * @example
1118
- * ```typescript
1119
- * const nonce = await this.getPermissionsUserNonce();
1120
- * console.log(`Current permissions nonce: ${nonce}`);
1121
- * ```
1122
- */
1123
- /**
1124
- * Retrieves the user's current nonce from the DataPortabilityPermissions contract.
1125
- *
1126
- * @remarks
1127
- * Used for permission-related operations (grant/revoke) to prevent replay attacks.
1128
- * The nonce must be incremented with each permission operation.
1129
- *
1130
- * @returns Promise resolving to the user's current nonce as a bigint
1131
- * @throws {NonceError} When retrieving the nonce fails
1132
- */
1133
- async getPermissionsUserNonce() {
1134
- try {
1135
- const userAddress = this.context.userAddress;
1136
- const chainId = await this.context.publicClient.getChainId();
1137
- const DataPortabilityPermissionsAddress = getContractAddress(
1138
- chainId,
1139
- "DataPortabilityPermissions"
1140
- );
1141
- const DataPortabilityPermissionsAbi = getAbi(
1142
- "DataPortabilityPermissions"
1143
- );
1144
- const nonce = await this.context.publicClient.readContract({
1145
- address: DataPortabilityPermissionsAddress,
1146
- abi: DataPortabilityPermissionsAbi,
1147
- functionName: "userNonce",
1148
- args: [userAddress]
1149
- });
1150
- return nonce;
1151
- } catch (error) {
1152
- throw new NonceError(
1153
- `Failed to retrieve permissions nonce: ${error instanceof Error ? error.message : "Unknown error"}`
1154
- );
1155
- }
1156
- }
1157
- /**
1158
- * Composes the EIP-712 typed data for PermissionGrant (new simplified format).
1159
- *
1160
- * @param params - The parameters for composing the permission grant message
1161
- * @param params.grantee - The recipient address for the permission grant
1162
- * @param params.operation - The type of operation being granted permission for
1163
- * @param params.files - Array of file IDs that the permission applies to
1164
- * @param params.grantUrl - URL where the grant details are stored
1165
- * @param params.serializedParameters - Serialized parameters for the operation
1166
- * @param params.nonce - Unique number to prevent replay attacks
1167
- * @returns Promise resolving to the typed data structure
1168
- */
1169
- async composePermissionGrantMessage(params) {
1170
- const domain = await this.getPermissionDomain();
1171
- console.debug(
1172
- "\u{1F50D} Debug - Composing permission message with grantUrl:",
1173
- params.grantUrl
1174
- );
1175
- const chainId = await this.context.publicClient.getChainId();
1176
- const DataPortabilityGranteesAddress = getContractAddress(
1177
- chainId,
1178
- "DataPortabilityGrantees"
1179
- );
1180
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
1181
- const granteeId = await this.context.publicClient.readContract({
1182
- address: DataPortabilityGranteesAddress,
1183
- abi: DataPortabilityGranteesAbi,
1184
- functionName: "granteeAddressToId",
1185
- args: [params.grantee]
1186
- });
1187
- if (!params.grantUrl.startsWith("ipfs://") && params.grantUrl.includes("/ipfs/")) {
1188
- const { extractIpfsHash } = await import("../utils/ipfs");
1189
- const hash = extractIpfsHash(params.grantUrl);
1190
- if (hash) {
1191
- console.warn(
1192
- `\u26A0\uFE0F Storing HTTP gateway URL on-chain instead of ipfs:// protocol. Found: ${params.grantUrl}. Consider using ipfs://${hash} for better protocol-agnostic on-chain storage.`
1193
- );
1194
- }
1195
- }
1196
- return {
1197
- domain,
1198
- types: {
1199
- Permission: [
1200
- { name: "nonce", type: "uint256" },
1201
- { name: "granteeId", type: "uint256" },
1202
- { name: "grant", type: "string" },
1203
- { name: "fileIds", type: "uint256[]" }
1204
- ]
1205
- },
1206
- primaryType: "Permission",
1207
- message: {
1208
- nonce: params.nonce,
1209
- granteeId,
1210
- grant: params.grantUrl,
1211
- fileIds: params.files.map((fileId) => BigInt(fileId))
1212
- }
1213
- };
1214
- }
1215
- /**
1216
- * Creates EIP-712 typed data structure for server files and permissions.
1217
- *
1218
- * @param params - Parameters for the server files and permissions message
1219
- * @param params.granteeId - Grantee ID
1220
- * @param params.grant - Grant URL or grant data
1221
- * @param params.fileUrls - Array of file URLs
1222
- * @param params.schemaIds - Schema IDs for each file
1223
- * @param params.serverAddress - Server address
1224
- * @param params.serverUrl - Server URL
1225
- * @param params.serverPublicKey - Server public key
1226
- * @param params.filePermissions - File permissions array
1227
- * @param params.nonce - Unique number to prevent replay attacks
1228
- * @returns Promise resolving to the typed data structure
1229
- */
1230
- async composeServerFilesAndPermissionMessage(params) {
1231
- const domain = await this.getPermissionDomain();
1232
- console.debug(
1233
- "\u{1F50D} Debug - Composing server files and permission message with grant:",
1234
- params.grant
1235
- );
1236
- if (!params.grant.startsWith("ipfs://") && params.grant.includes("/ipfs/")) {
1237
- const { extractIpfsHash } = await import("../utils/ipfs");
1238
- const hash = extractIpfsHash(params.grant);
1239
- if (hash) {
1240
- console.warn(
1241
- `\u26A0\uFE0F Storing HTTP gateway URL on-chain instead of ipfs:// protocol. Found: ${params.grant}. Consider using ipfs://${hash} for better protocol-agnostic on-chain storage.`
1242
- );
1243
- }
1244
- }
1245
- return {
1246
- domain,
1247
- types: {
1248
- Permission: [
1249
- { name: "account", type: "address" },
1250
- { name: "key", type: "string" }
1251
- ],
1252
- ServerFilesAndPermission: [
1253
- { name: "nonce", type: "uint256" },
1254
- { name: "granteeId", type: "uint256" },
1255
- { name: "grant", type: "string" },
1256
- { name: "fileUrls", type: "string[]" },
1257
- { name: "schemaIds", type: "uint256[]" },
1258
- { name: "serverAddress", type: "address" },
1259
- { name: "serverUrl", type: "string" },
1260
- { name: "serverPublicKey", type: "string" },
1261
- { name: "filePermissions", type: "Permission[][]" }
1262
- ]
1263
- },
1264
- primaryType: "ServerFilesAndPermission",
1265
- message: {
1266
- nonce: params.nonce,
1267
- granteeId: params.granteeId,
1268
- grant: params.grant,
1269
- fileUrls: params.fileUrls,
1270
- schemaIds: params.schemaIds.map((id) => BigInt(id)),
1271
- serverAddress: params.serverAddress,
1272
- serverUrl: params.serverUrl,
1273
- serverPublicKey: params.serverPublicKey,
1274
- filePermissions: params.filePermissions
1275
- }
1276
- };
1277
- }
1278
- /**
1279
- * Gets the EIP-712 domain for PermissionGrant signatures.
1280
- *
1281
- * @returns Promise resolving to the EIP-712 domain configuration
1282
- */
1283
- async getPermissionDomain() {
1284
- const chainId = await this.context.publicClient.getChainId();
1285
- const DataPortabilityPermissionsAddress = getContractAddress(
1286
- chainId,
1287
- "DataPortabilityPermissions"
1288
- );
1289
- return {
1290
- name: "VanaDataPortabilityPermissions",
1291
- version: "1",
1292
- chainId,
1293
- verifyingContract: DataPortabilityPermissionsAddress
1294
- };
1295
- }
1296
- /**
1297
- * Signs typed data using the wallet client with signature caching.
1298
- *
1299
- * @param typedData - The EIP-712 typed data structure to sign
1300
- * @returns Promise resolving to the cryptographic signature
1301
- */
1302
- async signTypedData(typedData) {
1303
- this.assertWallet();
1304
- try {
1305
- const walletAddress = this.context.walletClient.account?.address ?? this.context.userAddress;
1306
- return await withSignatureCache(
1307
- this.context.platform.cache,
1308
- walletAddress,
1309
- typedData,
1310
- async () => {
1311
- const viemCompatibleTypedData = toViemTypedDataDefinition(typedData);
1312
- return await this.context.walletClient.signTypedData({
1313
- ...viemCompatibleTypedData,
1314
- // Use the account if available, otherwise use the wallet address
1315
- // This follows the same pattern used throughout this file
1316
- account: this.context.walletClient.account ?? walletAddress
1317
- });
1318
- }
1319
- );
1320
- } catch (error) {
1321
- if (error instanceof Error && error.message.includes("rejected")) {
1322
- throw new UserRejectedRequestError();
1323
- }
1324
- throw new SignatureError(
1325
- `Failed to sign typed data: ${error instanceof Error ? error.message : "Unknown error"}`,
1326
- error
1327
- );
1328
- }
1329
- }
1330
- /**
1331
- * Gets the user's address from the context.
1332
- *
1333
- * @returns The user's address
1334
- */
1335
- /**
1336
- * Gets on-chain permission grant data without expensive off-chain resolution.
1337
- *
1338
- * @remarks
1339
- * This method provides a fast, performance-focused way to retrieve permission grants
1340
- * by querying only the subgraph without making expensive IPFS or individual contract calls.
1341
- * It eliminates the N+1 query problem of the legacy `getUserPermissions()` method.
1342
- *
1343
- * The returned data contains all on-chain information but does NOT include resolved
1344
- * operation details, parameters, or file IDs. Use `retrieveGrantFile()` separately
1345
- * for specific grants when detailed data is needed.
1346
- *
1347
- * **Performance**: Completes in ~100-500ms regardless of permission count.
1348
- * **Reliability**: Single point of failure (subgraph) with clear RPC fallback path.
1349
- *
1350
- * @param options - Options for retrieving permissions (limit, subgraph URL)
1351
- * @returns A Promise that resolves to an array of `OnChainPermissionGrant` objects
1352
- * @throws {BlockchainError} When subgraph query fails
1353
- * @throws {NetworkError} When network requests fail
1354
- * @example
1355
- * ```typescript
1356
- * // Fast: Get all on-chain permission data
1357
- * const grants = await vana.permissions.getUserPermissionGrantsOnChain({ limit: 20 });
1358
- *
1359
- * // Display in UI immediately
1360
- * grants.forEach(grant => {
1361
- * console.log(`Permission ${grant.id}: ${grant.grantUrl}`);
1362
- * });
1363
- *
1364
- * // Lazy load detailed data for specific permission when user clicks
1365
- * const grantFile = await retrieveGrantFile(grants[0].grantUrl);
1366
- * console.log(`Operation: ${grantFile.operation}`);
1367
- * console.log(`Parameters:`, grantFile.parameters);
1368
- * ```
1369
- */
1370
- async getUserPermissionGrantsOnChain(options = {}) {
1371
- const { limit = 50, fetchAll = false, subgraphUrl } = options;
1372
- const pageSize = fetchAll ? 100 : limit;
1373
- const maxResults = fetchAll ? 1e4 : limit;
1374
- try {
1375
- const userAddress = this.context.userAddress;
1376
- const graphqlEndpoint = subgraphUrl ?? this.context.subgraphUrl;
1377
- if (!graphqlEndpoint) {
1378
- throw new BlockchainError(
1379
- "subgraphUrl is required. Please provide a valid subgraph endpoint or configure it in Vana constructor."
1380
- );
1381
- }
1382
- const query = `
1383
- query GetUserPermissions($userId: ID!, $first: Int!, $skip: Int!) {
1384
- user(id: $userId) {
1385
- id
1386
- permissions(first: $first, skip: $skip, orderBy: addedAtBlock, orderDirection: desc) {
1387
- id
1388
- grant
1389
- nonce
1390
- signature
1391
- startBlock
1392
- endBlock
1393
- addedAtBlock
1394
- addedAtTimestamp
1395
- transactionHash
1396
- grantee {
1397
- id
1398
- address
1399
- }
1400
- }
1401
- }
1402
- }
1403
- `;
1404
- const allPermissions = [];
1405
- let currentOffset = 0;
1406
- if (!fetchAll) {
1407
- const response = await fetch(graphqlEndpoint, {
1408
- method: "POST",
1409
- headers: {
1410
- "Content-Type": "application/json"
1411
- },
1412
- body: JSON.stringify({
1413
- query,
1414
- variables: {
1415
- userId: userAddress.toLowerCase(),
1416
- first: limit,
1417
- skip: 0
1418
- }
1419
- })
1420
- });
1421
- if (!response.ok) {
1422
- throw new BlockchainError(
1423
- `Subgraph request failed: ${response.status} ${response.statusText}`
1424
- );
1425
- }
1426
- const result = await response.json();
1427
- if (result.errors) {
1428
- throw new BlockchainError(
1429
- `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
1430
- );
1431
- }
1432
- const userData = result.data?.user;
1433
- if (!userData?.permissions?.length) {
1434
- return [];
1435
- }
1436
- allPermissions.push(...userData.permissions);
1437
- } else {
1438
- while (allPermissions.length < maxResults) {
1439
- const currentLimit = Math.min(
1440
- pageSize,
1441
- maxResults - allPermissions.length
1442
- );
1443
- const response = await fetch(graphqlEndpoint, {
1444
- method: "POST",
1445
- headers: {
1446
- "Content-Type": "application/json"
1447
- },
1448
- body: JSON.stringify({
1449
- query,
1450
- variables: {
1451
- userId: userAddress.toLowerCase(),
1452
- first: currentLimit,
1453
- skip: currentOffset
1454
- }
1455
- })
1456
- });
1457
- if (!response.ok) {
1458
- throw new BlockchainError(
1459
- `Subgraph request failed: ${response.status} ${response.statusText}`
1460
- );
1461
- }
1462
- const result = await response.json();
1463
- if (result.errors) {
1464
- throw new BlockchainError(
1465
- `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
1466
- );
1467
- }
1468
- const userData = result.data?.user;
1469
- if (!userData?.permissions?.length) {
1470
- break;
1471
- }
1472
- allPermissions.push(...userData.permissions);
1473
- if (userData.permissions.length < currentLimit) {
1474
- break;
1475
- }
1476
- currentOffset += userData.permissions.length;
1477
- }
1478
- }
1479
- const onChainGrants = allPermissions.map(
1480
- (permission) => {
1481
- const endBlock = permission.endBlock === void 0 || permission.endBlock === null ? 0n : BigInt(permission.endBlock);
1482
- const active = !permission.endBlock || endBlock === 0n || endBlock === MAX_UINT256;
1483
- return {
1484
- id: BigInt(permission.id),
1485
- grantUrl: permission.grant,
1486
- grantSignature: permission.signature,
1487
- nonce: BigInt(permission.nonce),
1488
- startBlock: BigInt(permission.startBlock),
1489
- endBlock,
1490
- addedAtBlock: BigInt(permission.addedAtBlock),
1491
- addedAtTimestamp: BigInt(permission.addedAtTimestamp ?? "0"),
1492
- transactionHash: permission.transactionHash ?? "",
1493
- grantor: userAddress,
1494
- grantee: permission.grantee,
1495
- active
1496
- };
1497
- }
1498
- );
1499
- return onChainGrants.sort((a, b) => {
1500
- if (a.id < b.id) return 1;
1501
- if (a.id > b.id) return -1;
1502
- return 0;
1503
- });
1504
- } catch (error) {
1505
- if (error instanceof BlockchainError || error instanceof NetworkError) {
1506
- throw error;
1507
- }
1508
- throw new BlockchainError(
1509
- `Failed to fetch user permission grants: ${error instanceof Error ? error.message : "Unknown error"}`
1510
- );
1511
- }
1512
- }
1513
- /**
1514
- * Registers a new server and immediately trusts it in the DataPortabilityServers contract.
1515
- *
1516
- * This is a combined operation that both registers a new data portability server
1517
- * and adds it to the user's trusted servers list in a single transaction.
1518
- * Trusted servers can handle data export and portability requests from the user.
1519
- *
1520
- * @param params - Parameters for adding and trusting the server
1521
- * @param params.serverAddress - Ethereum address of the server
1522
- * @param params.serverUrl - HTTPS URL where the server can be reached
1523
- * @param params.publicKey - Server's public key for encryption (hex string)
1524
- * @returns Promise resolving to transaction hash
1525
- * @throws {UserRejectedRequestError} When user rejects the transaction
1526
- * @throws {BlockchainError} When chain ID is unavailable or transaction fails
1527
- * @throws {ServerAlreadyRegisteredError} When server address is already registered
1528
- * @throws {Error} When wallet account is not available
1529
- *
1530
- * @example
1531
- * ```typescript
1532
- * // Add and trust a server by providing all required details
1533
- * const txHash = await vana.permissions.addAndTrustServer({
1534
- * owner: '0x1234567890abcdef1234567890abcdef12345678',
1535
- * serverAddress: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
1536
- * serverUrl: 'https://myserver.example.com',
1537
- * publicKey: '0x456789abcdef456789abcdef456789abcdef456789abcdef'
1538
- * });
1539
- * console.log('Server added and trusted in transaction:', txHash);
1540
- *
1541
- * // Verify the server is now trusted
1542
- * const trustedServers = await vana.permissions.getTrustedServers();
1543
- * console.log('Now trusting servers:', trustedServers);
1544
- * ```
1545
- */
1546
- async addAndTrustServer(params) {
1547
- this.assertWallet();
1548
- try {
1549
- const chainId = await this.context.walletClient.getChainId();
1550
- const DataPortabilityServersAddress = getContractAddress(
1551
- chainId,
1552
- "DataPortabilityServers"
1553
- );
1554
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
1555
- const account = this.context.walletClient?.account ?? this.context.userAddress;
1556
- const userAddress = typeof account === "string" ? account : account.address;
1557
- const normalizedUserAddress = getAddress(userAddress);
1558
- const normalizedServerAddress = getAddress(params.serverAddress);
1559
- const txHash = await this.context.walletClient.writeContract({
1560
- address: DataPortabilityServersAddress,
1561
- abi: DataPortabilityServersAbi,
1562
- functionName: "addAndTrustServerByManager",
1563
- args: [
1564
- normalizedUserAddress,
1565
- {
1566
- serverAddress: normalizedServerAddress,
1567
- serverUrl: params.serverUrl,
1568
- publicKey: params.publicKey
1569
- }
1570
- ],
1571
- account,
1572
- chain: this.context.walletClient?.chain ?? null
1573
- });
1574
- const { tx } = await import("../utils/transactionHelpers");
1575
- const txResult = tx({
1576
- hash: txHash,
1577
- from: userAddress,
1578
- contract: "DataPortabilityServers",
1579
- fn: "addAndTrustServerByManager"
1580
- });
1581
- if (!this.context.waitForTransactionEvents) {
1582
- throw new BlockchainError("waitForTransactionEvents not configured");
1583
- }
1584
- const result = await this.context.waitForTransactionEvents(txResult);
1585
- const event = result.expectedEvents.ServerTrusted;
1586
- if (!event) {
1587
- throw new BlockchainError(
1588
- "ServerTrusted event not found in transaction"
1589
- );
1590
- }
1591
- const receipt = await this.context.publicClient.getTransactionReceipt({
1592
- hash: txHash
1593
- });
1594
- return {
1595
- transactionHash: txHash,
1596
- blockNumber: receipt.blockNumber,
1597
- gasUsed: receipt.gasUsed,
1598
- user: event.user,
1599
- serverId: event.serverId,
1600
- // bigint from event
1601
- serverAddress: normalizedServerAddress,
1602
- // derived from params
1603
- serverUrl: params.serverUrl
1604
- // provided in params
1605
- };
1606
- } catch (error) {
1607
- if (error instanceof Error && error.message.includes("rejected")) {
1608
- throw new UserRejectedRequestError();
1609
- }
1610
- throw new BlockchainError(
1611
- `Failed to add and trust server: ${error instanceof Error ? error.message : "Unknown error"}`,
1612
- error
1613
- );
1614
- }
1615
- }
1616
- /**
1617
- * Trusts a server for data processing (legacy method).
1618
- *
1619
- * @param params - Parameters for trusting the server
1620
- * @returns Promise resolving to transaction hash
1621
- * @deprecated Use addAndTrustServer instead
1622
- */
1623
- async submitTrustServer(params) {
1624
- this.assertWallet();
1625
- try {
1626
- const chainId = await this.context.walletClient.getChainId();
1627
- const DataPortabilityServersAddress = getContractAddress(
1628
- chainId,
1629
- "DataPortabilityServers"
1630
- );
1631
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
1632
- const account = this.context.walletClient?.account ?? this.context.userAddress;
1633
- const txHash = await this.context.walletClient.writeContract({
1634
- address: DataPortabilityServersAddress,
1635
- abi: DataPortabilityServersAbi,
1636
- functionName: "trustServer",
1637
- args: [BigInt(params.serverId)],
1638
- account,
1639
- chain: this.context.walletClient?.chain ?? null
1640
- });
1641
- const { tx } = await import("../utils/transactionHelpers");
1642
- return tx({
1643
- hash: txHash,
1644
- from: typeof account === "string" ? account : account.address,
1645
- contract: "DataPortabilityServers",
1646
- fn: "trustServer"
1647
- });
1648
- } catch (error) {
1649
- if (error instanceof Error && error.message.includes("rejected")) {
1650
- throw new UserRejectedRequestError();
1651
- }
1652
- throw new BlockchainError(
1653
- `Failed to trust server: ${error instanceof Error ? error.message : "Unknown error"}`,
1654
- error
1655
- );
1656
- }
1657
- }
1658
- /**
1659
- * Adds and trusts a server using a signature (gasless transaction).
1660
- *
1661
- * @param params - Parameters for adding and trusting the server
1662
- * @returns Promise resolving to TransactionResult with ServerTrustResult event data
1663
- */
1664
- async submitAddAndTrustServerWithSignature(params, options) {
1665
- this.assertWallet();
1666
- try {
1667
- const nonce = await this.getServersUserNonce();
1668
- const serverAddress = getAddress(params.serverAddress);
1669
- const addAndTrustServerInput = {
1670
- nonce,
1671
- serverAddress,
1672
- publicKey: params.publicKey,
1673
- serverUrl: params.serverUrl
1674
- };
1675
- const typedData = await this.composeAddAndTrustServerMessage(
1676
- addAndTrustServerInput
1677
- );
1678
- console.debug("\u{1F50D} AddAndTrustServer Debug Info:", {
1679
- nonce: nonce.toString(),
1680
- serverAddress: params.serverAddress,
1681
- publicKey: params.publicKey,
1682
- serverUrl: params.serverUrl,
1683
- domain: typedData.domain,
1684
- typedDataMessage: typedData.message
1685
- });
1686
- const signature = await this.signTypedData(typedData);
1687
- console.debug("\u{1F50D} Generated signature:", signature);
1688
- let hash;
1689
- if (this.context.relayer) {
1690
- const request = {
1691
- type: "signed",
1692
- operation: "submitAddAndTrustServer",
1693
- typedData,
1694
- signature
1695
- };
1696
- const response = await this.context.relayer(request);
1697
- if (response.type === "error") {
1698
- throw new RelayerError(response.error);
1699
- }
1700
- if (response.type === "submitted") {
1701
- hash = response.hash;
1702
- } else if (response.type === "signed") {
1703
- hash = response.hash;
1704
- } else {
1705
- throw new Error("Unexpected response type from relayer");
1706
- }
1707
- } else {
1708
- hash = await this.submitAddAndTrustServerTransaction(
1709
- addAndTrustServerInput,
1710
- signature,
1711
- options
1712
- );
1713
- }
1714
- const account = this.context.walletClient?.account ?? this.context.userAddress;
1715
- const { tx } = await import("../utils/transactionHelpers");
1716
- return tx({
1717
- hash,
1718
- from: typeof account === "string" ? account : account.address,
1719
- contract: "DataPortabilityServers",
1720
- fn: "addAndTrustServerWithSignature"
1721
- });
1722
- } catch (error) {
1723
- if (error instanceof Error) {
1724
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
1725
- throw error;
1726
- }
1727
- throw new BlockchainError(
1728
- `Add and trust server failed: ${error.message}`,
1729
- error
1730
- );
1731
- }
1732
- throw new BlockchainError(
1733
- "Add and trust server failed with unknown error"
1734
- );
1735
- }
1736
- }
1737
- /**
1738
- * Trusts a server using a signature (gasless transaction - legacy method).
1739
- *
1740
- * @param params - Parameters for trusting the server
1741
- * @returns Promise resolving to transaction hash
1742
- * @deprecated Use addAndTrustServerWithSignature instead
1743
- * @throws {BlockchainError} When chain ID is not available
1744
- * @throws {NonceError} When retrieving user nonce fails
1745
- * @throws {SignatureError} When user rejects the signature request
1746
- * @throws {RelayerError} When gasless submission fails
1747
- * @throws {ServerUrlMismatchError} When server URL doesn't match existing registration
1748
- * @throws {BlockchainError} When trust operation fails for any other reason
1749
- */
1750
- async submitTrustServerWithSignature(params, options) {
1751
- this.assertWallet();
1752
- try {
1753
- const nonce = await this.getServersUserNonce();
1754
- const trustServerInput = {
1755
- nonce,
1756
- serverId: params.serverId
1757
- };
1758
- const typedData = await this.composeTrustServerMessage(trustServerInput);
1759
- const signature = await this.signTypedData(typedData);
1760
- let hash;
1761
- if (this.context.relayer) {
1762
- const request = {
1763
- type: "signed",
1764
- operation: "submitTrustServer",
1765
- typedData,
1766
- signature
1767
- };
1768
- const response = await this.context.relayer(request);
1769
- if (response.type === "error") {
1770
- throw new RelayerError(response.error);
1771
- }
1772
- if (response.type === "submitted") {
1773
- hash = response.hash;
1774
- } else if (response.type === "signed") {
1775
- hash = response.hash;
1776
- } else {
1777
- throw new Error("Unexpected response type from relayer");
1778
- }
1779
- } else {
1780
- hash = await this.submitTrustServerTransaction(
1781
- trustServerInput,
1782
- signature,
1783
- options
1784
- );
1785
- }
1786
- const account = this.context.walletClient?.account ?? this.context.userAddress;
1787
- const { tx } = await import("../utils/transactionHelpers");
1788
- return tx({
1789
- hash,
1790
- from: typeof account === "string" ? account : account.address,
1791
- contract: "DataPortabilityServers",
1792
- fn: "trustServerWithSignature"
1793
- });
1794
- } catch (error) {
1795
- if (error instanceof Error) {
1796
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
1797
- throw error;
1798
- }
1799
- throw new BlockchainError(
1800
- `Trust server failed: ${error.message}`,
1801
- error
1802
- );
1803
- }
1804
- throw new BlockchainError("Trust server failed with unknown error");
1805
- }
1806
- }
1807
- /**
1808
- * Submits a direct untrust server transaction (without signature).
1809
- *
1810
- * @param params - The untrust server parameters containing server details
1811
- * @returns Promise resolving to the transaction hash
1812
- */
1813
- /**
1814
- * Submits an untrust server transaction directly to the blockchain.
1815
- *
1816
- * @remarks
1817
- * Internal method used for direct blockchain submission of untrust server operations
1818
- * when relayer callbacks are not available.
1819
- *
1820
- * @param params - The untrust server parameters
1821
- * @returns Promise resolving to TransactionResult for transaction tracking
1822
- * @throws {BlockchainError} When contract submission fails
1823
- */
1824
- async submitDirectUntrustTransaction(params, options) {
1825
- this.assertWallet();
1826
- try {
1827
- const chainId = await this.context.walletClient.getChainId();
1828
- const DataPortabilityServersAddress = getContractAddress(
1829
- chainId,
1830
- "DataPortabilityServers"
1831
- );
1832
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
1833
- const account = this.context.walletClient?.account ?? this.context.userAddress;
1834
- const txHash = await this.context.walletClient.writeContract({
1835
- address: DataPortabilityServersAddress,
1836
- abi: DataPortabilityServersAbi,
1837
- functionName: "untrustServer",
1838
- args: [BigInt(params.serverId)],
1839
- account,
1840
- chain: this.context.walletClient?.chain ?? null,
1841
- ...options?.gas && { gas: options.gas },
1842
- ...options?.nonce && { nonce: options.nonce },
1843
- // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
1844
- ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
1845
- ...options.maxFeePerGas && {
1846
- maxFeePerGas: options.maxFeePerGas
1847
- },
1848
- ...options.maxPriorityFeePerGas && {
1849
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
1850
- }
1851
- } : options?.gasPrice && { gasPrice: options.gasPrice }
1852
- });
1853
- const { tx } = await import("../utils/transactionHelpers");
1854
- return tx({
1855
- hash: txHash,
1856
- from: typeof account === "string" ? account : account.address,
1857
- contract: "DataPortabilityServers",
1858
- fn: "untrustServer"
1859
- });
1860
- } catch (error) {
1861
- if (error instanceof Error && error.message.includes("rejected")) {
1862
- throw new UserRejectedRequestError();
1863
- }
1864
- throw new BlockchainError(
1865
- `Failed to untrust server: ${error instanceof Error ? error.message : "Unknown error"}`,
1866
- error
1867
- );
1868
- }
1869
- }
1870
- /**
1871
- * Removes a server from the user's trusted servers list in the DataPortabilityServers contract.
1872
- *
1873
- * This revokes the server's authorization to handle data portability requests for the user.
1874
- * The server remains registered in the system but will no longer be trusted by this user.
1875
- *
1876
- * @param params - Parameters for untrusting the server
1877
- * @param params.serverId - The numeric ID of the server to untrust
1878
- * @param options - Optional transaction options for gas parameters and timeout
1879
- * @returns Promise resolving to transaction hash
1880
- * @throws {Error} When wallet account is not available
1881
- * @throws {NonceError} When retrieving user nonce fails
1882
- * @throws {UserRejectedRequestError} When user rejects the transaction
1883
- * @throws {ServerNotTrustedError} When the server is not currently trusted
1884
- * @throws {BlockchainError} When untrust transaction fails
1885
- *
1886
- * @example
1887
- * ```typescript
1888
- * // Untrust a specific server
1889
- * const txHash = await vana.permissions.untrustServer({
1890
- * serverId: 1
1891
- * });
1892
- * console.log('Server untrusted in transaction:', txHash);
1893
- *
1894
- * // Verify the server is no longer trusted
1895
- * const trustedServers = await vana.permissions.getTrustedServers();
1896
- * console.log('Still trusting servers:', trustedServers);
1897
- * ```
1898
- */
1899
- async submitUntrustServer(params, options) {
1900
- this.assertWallet();
1901
- const nonce = await this.getServersUserNonce();
1902
- const untrustServerInput = {
1903
- nonce,
1904
- serverId: params.serverId
1905
- };
1906
- return await this.submitDirectUntrustTransaction(
1907
- untrustServerInput,
1908
- options
1909
- );
1910
- }
1911
- /**
1912
- * Untrusts a server using a signature (gasless transaction).
1913
- *
1914
- * @param params - Parameters for untrusting the server
1915
- * @param params.serverId - The server's Ethereum address to untrust
1916
- * @returns Promise resolving to transaction hash
1917
- * @throws {Error} When wallet account is not available
1918
- * @throws {NonceError} When retrieving user nonce fails
1919
- * @throws {SignatureError} When user rejects the signature request
1920
- * @throws {RelayerError} When gasless submission fails
1921
- * @throws {BlockchainError} When untrust transaction fails
1922
- */
1923
- async submitUntrustServerWithSignature(params) {
1924
- this.assertWallet();
1925
- try {
1926
- const nonce = await this.getServersUserNonce();
1927
- const untrustServerInput = {
1928
- nonce,
1929
- serverId: params.serverId
1930
- };
1931
- const typedData = await this.composeUntrustServerMessage(untrustServerInput);
1932
- const signature = await this.signTypedData(typedData);
1933
- let hash;
1934
- if (this.context.relayer) {
1935
- const request = {
1936
- type: "signed",
1937
- operation: "submitUntrustServer",
1938
- typedData,
1939
- signature
1940
- };
1941
- const response = await this.context.relayer(request);
1942
- if (response.type === "error") {
1943
- throw new RelayerError(response.error);
1944
- }
1945
- if (response.type === "submitted") {
1946
- hash = response.hash;
1947
- } else if (response.type === "signed") {
1948
- hash = response.hash;
1949
- } else {
1950
- throw new Error("Unexpected response type from relayer");
1951
- }
1952
- } else {
1953
- hash = await this.submitSignedUntrustTransaction(typedData, signature);
1954
- }
1955
- const account = this.context.walletClient?.account ?? this.context.userAddress;
1956
- const { tx } = await import("../utils/transactionHelpers");
1957
- return tx({
1958
- hash,
1959
- from: typeof account === "string" ? account : account.address,
1960
- contract: "DataPortabilityServers",
1961
- fn: "untrustServerWithSignature"
1962
- });
1963
- } catch (error) {
1964
- if (error instanceof Error) {
1965
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
1966
- throw error;
1967
- }
1968
- throw new BlockchainError(
1969
- `Untrust server failed: ${error.message}`,
1970
- error
1971
- );
1972
- }
1973
- throw new BlockchainError("Untrust server failed with unknown error");
1974
- }
1975
- }
1976
- /**
1977
- * Retrieves all servers trusted by a user from the DataPortabilityServers contract.
1978
- *
1979
- * Returns an array of server IDs that the specified user has explicitly trusted.
1980
- * Trusted servers are those that users have authorized to handle their data portability requests.
1981
- *
1982
- * @param userAddress - Optional user address to query (defaults to current wallet user)
1983
- * @returns Promise resolving to array of trusted server IDs (numeric)
1984
- * @throws {BlockchainError} When reading from contract fails or chain is unavailable
1985
- * @throws {NetworkError} When unable to connect to the blockchain network
1986
- *
1987
- * @example
1988
- * ```typescript
1989
- * // Get trusted servers for current user
1990
- * const myServers = await vana.permissions.getTrustedServers();
1991
- * console.log(`I trust ${myServers.length} servers: ${myServers.join(', ')}`);
1992
- *
1993
- * // Get trusted servers for another user
1994
- * const userServers = await vana.permissions.getTrustedServers("0x1234...");
1995
- * console.log(`User trusts servers: ${userServers.join(', ')}`);
1996
- * ```
1997
- */
1998
- async getTrustedServers(userAddress) {
1999
- try {
2000
- const user = userAddress ?? this.context.userAddress;
2001
- const chainId = await this.context.publicClient.getChainId();
2002
- const DataPortabilityServersAddress = getContractAddress(
2003
- chainId,
2004
- "DataPortabilityServers"
2005
- );
2006
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2007
- const serverIds = await this.context.publicClient.readContract({
2008
- address: DataPortabilityServersAddress,
2009
- abi: DataPortabilityServersAbi,
2010
- functionName: "userServerIdsValues",
2011
- args: [user]
2012
- });
2013
- return serverIds.map((id) => Number(id));
2014
- } catch (error) {
2015
- throw new BlockchainError(
2016
- `Failed to get trusted servers: ${error instanceof Error ? error.message : "Unknown error"}`,
2017
- error
2018
- );
2019
- }
2020
- }
2021
- /**
2022
- * Gets the total count of trusted servers for a user.
2023
- *
2024
- * @param userAddress - Optional user address (defaults to current user)
2025
- * @returns Promise resolving to the number of trusted servers
2026
- * @throws {BlockchainError} When reading from contract fails or chain is unavailable
2027
- */
2028
- async getTrustedServersCount(userAddress) {
2029
- try {
2030
- const user = userAddress ?? this.context.userAddress;
2031
- const chainId = await this.context.publicClient.getChainId();
2032
- const DataPortabilityServersAddress = getContractAddress(
2033
- chainId,
2034
- "DataPortabilityServers"
2035
- );
2036
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2037
- const count = await this.context.publicClient.readContract({
2038
- address: DataPortabilityServersAddress,
2039
- abi: DataPortabilityServersAbi,
2040
- functionName: "userServerIdsLength",
2041
- args: [user]
2042
- });
2043
- return Number(count);
2044
- } catch (error) {
2045
- throw new BlockchainError(
2046
- `Failed to get trusted servers count: ${error instanceof Error ? error.message : "Unknown error"}`,
2047
- error
2048
- );
2049
- }
2050
- }
2051
- /**
2052
- * Gets trusted servers with pagination support.
2053
- *
2054
- * @param options - Query options including pagination parameters
2055
- * @returns Promise resolving to paginated trusted servers
2056
- * @throws {BlockchainError} When reading from contract fails or chain is unavailable
2057
- */
2058
- async getTrustedServersPaginated(options = {}) {
2059
- try {
2060
- const user = options.userAddress ?? this.context.userAddress;
2061
- const limit = options.limit ?? 50;
2062
- const offset = options.offset ?? 0;
2063
- const chainId = await this.context.publicClient.getChainId();
2064
- const DataPortabilityServersAddress = getContractAddress(
2065
- chainId,
2066
- "DataPortabilityServers"
2067
- );
2068
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2069
- const totalCount = await this.context.publicClient.readContract({
2070
- address: DataPortabilityServersAddress,
2071
- abi: DataPortabilityServersAbi,
2072
- functionName: "userServerIdsLength",
2073
- args: [user]
2074
- });
2075
- const total = Number(totalCount);
2076
- if (offset >= total) {
2077
- return {
2078
- servers: [],
2079
- total,
2080
- offset,
2081
- limit,
2082
- hasMore: false
2083
- };
2084
- }
2085
- const endIndex = Math.min(offset + limit, total);
2086
- const serverIdCalls = [];
2087
- for (let i = offset; i < endIndex; i++) {
2088
- serverIdCalls.push({
2089
- address: DataPortabilityServersAddress,
2090
- abi: DataPortabilityServersAbi,
2091
- functionName: "userServerIdsAt",
2092
- args: [user, BigInt(i)]
2093
- });
2094
- }
2095
- const serverIdResults = await gasAwareMulticall(this.context.publicClient, {
2096
- contracts: serverIdCalls
2097
- });
2098
- const servers = serverIdResults.map((result) => Number(result)).filter((id) => id > 0);
2099
- return {
2100
- servers,
2101
- total,
2102
- offset,
2103
- limit,
2104
- hasMore: offset + limit < total
2105
- };
2106
- } catch (error) {
2107
- throw new BlockchainError(
2108
- `Failed to get paginated trusted servers: ${error instanceof Error ? error.message : "Unknown error"}`,
2109
- error
2110
- );
2111
- }
2112
- }
2113
- /**
2114
- * Gets trusted servers with their complete information.
2115
- *
2116
- * @param options - Query options
2117
- * @returns Promise resolving to array of trusted server info
2118
- * @throws {BlockchainError} When reading from contract fails or chain is unavailable
2119
- */
2120
- async getTrustedServersWithInfo(options = {}) {
2121
- try {
2122
- const paginatedResult = await this.getTrustedServersPaginated(options);
2123
- const chainId = await this.context.publicClient.getChainId();
2124
- const DataPortabilityServersAddress = getContractAddress(
2125
- chainId,
2126
- "DataPortabilityServers"
2127
- );
2128
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2129
- const serverInfoCalls = paginatedResult.servers.map(
2130
- (serverId) => ({
2131
- address: DataPortabilityServersAddress,
2132
- abi: DataPortabilityServersAbi,
2133
- functionName: "servers",
2134
- args: [BigInt(serverId)]
2135
- })
2136
- );
2137
- const serverInfoResults = await gasAwareMulticall(this.context.publicClient, {
2138
- contracts: serverInfoCalls,
2139
- allowFailure: true
2140
- });
2141
- return serverInfoResults.map((result, index) => {
2142
- const serverId = paginatedResult.servers[index];
2143
- if (result.status === "success" && result.result) {
2144
- const serverInfo = result.result;
2145
- return {
2146
- id: BigInt(serverId),
2147
- owner: serverInfo.owner,
2148
- serverAddress: serverInfo.serverAddress,
2149
- publicKey: serverInfo.publicKey,
2150
- url: serverInfo.url,
2151
- startBlock: 0n,
2152
- // We don't have this info from the old method structure
2153
- endBlock: 0n
2154
- // 0 means still active
2155
- };
2156
- } else {
2157
- return {
2158
- id: BigInt(serverId),
2159
- owner: "0x0000000000000000000000000000000000000000",
2160
- serverAddress: "0x0000000000000000000000000000000000000000",
2161
- publicKey: "",
2162
- url: "",
2163
- startBlock: 0n,
2164
- endBlock: 0n
2165
- };
2166
- }
2167
- });
2168
- } catch (error) {
2169
- throw new BlockchainError(
2170
- `Failed to get trusted servers with info: ${error instanceof Error ? error.message : "Unknown error"}`,
2171
- error
2172
- );
2173
- }
2174
- }
2175
- /**
2176
- * Gets server information for multiple servers efficiently.
2177
- *
2178
- * @remarks
2179
- * This method uses multicall to fetch information for multiple servers in a single
2180
- * blockchain call, improving performance when querying many servers. Failed lookups
2181
- * are returned separately for error handling.
2182
- *
2183
- * @param serverIds - Array of numeric server IDs to query
2184
- * @returns Promise resolving to batch result containing successful lookups and failed IDs
2185
- * @throws {BlockchainError} When reading from contract fails or chain is unavailable
2186
- * @example
2187
- * ```typescript
2188
- * const result = await vana.permissions.getServerInfoBatch([1, 2, 3, 999]);
2189
- *
2190
- * // Process successful lookups
2191
- * result.servers.forEach((server, id) => {
2192
- * console.log(`Server ${id}: ${server.url}`);
2193
- * });
2194
- *
2195
- * // Handle failed lookups
2196
- * if (result.failed.length > 0) {
2197
- * console.log(`Failed to fetch: ${result.failed.join(', ')}`);
2198
- * }
2199
- * ```
2200
- */
2201
- async getServerInfoBatch(serverIds) {
2202
- if (serverIds.length === 0) {
2203
- return {
2204
- servers: /* @__PURE__ */ new Map(),
2205
- failed: []
2206
- };
2207
- }
2208
- try {
2209
- const chainId = await this.context.publicClient.getChainId();
2210
- const DataPortabilityServersAddress = getContractAddress(
2211
- chainId,
2212
- "DataPortabilityServers"
2213
- );
2214
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2215
- const serverInfoCalls = serverIds.map(
2216
- (serverId) => ({
2217
- address: DataPortabilityServersAddress,
2218
- abi: DataPortabilityServersAbi,
2219
- functionName: "servers",
2220
- args: [BigInt(serverId)]
2221
- })
2222
- );
2223
- const serverInfoResults = await gasAwareMulticall(this.context.publicClient, {
2224
- contracts: serverInfoCalls,
2225
- allowFailure: true
2226
- });
2227
- const results = serverInfoResults.map((result, index) => {
2228
- const serverId = serverIds[index];
2229
- if (result.status === "success" && result.result) {
2230
- const serverInfo = result.result;
2231
- const server = {
2232
- id: Number(serverInfo.id),
2233
- owner: serverInfo.owner,
2234
- url: serverInfo.url,
2235
- serverAddress: serverInfo.serverAddress,
2236
- publicKey: serverInfo.publicKey
2237
- };
2238
- return { serverId, server, success: true };
2239
- } else {
2240
- return { serverId, server: null, success: false };
2241
- }
2242
- });
2243
- const servers = /* @__PURE__ */ new Map();
2244
- const failed = [];
2245
- for (const result of results) {
2246
- if (result.success && result.server) {
2247
- servers.set(result.serverId, result.server);
2248
- } else {
2249
- failed.push(result.serverId);
2250
- }
2251
- }
2252
- return { servers, failed };
2253
- } catch (error) {
2254
- throw new BlockchainError(
2255
- `Failed to batch get server info: ${error instanceof Error ? error.message : "Unknown error"}`,
2256
- error
2257
- );
2258
- }
2259
- }
2260
- /**
2261
- * Checks whether a specific server is trusted by a user.
2262
- *
2263
- * @remarks
2264
- * This method queries the user's trusted server list and checks if the specified
2265
- * server is present. Returns both the trust status and the index in the trust list
2266
- * if trusted.
2267
- *
2268
- * @param serverId - Numeric server ID to check
2269
- * @param userAddress - Optional user address (defaults to current user)
2270
- * @returns Promise resolving to server trust status with trust index if applicable
2271
- * @throws {BlockchainError} When reading from contract fails
2272
- * @example
2273
- * ```typescript
2274
- * const status = await vana.permissions.checkServerTrustStatus(1);
2275
- * if (status.isTrusted) {
2276
- * console.log(`Server is trusted at index ${status.trustIndex}`);
2277
- * } else {
2278
- * console.log('Server is not trusted');
2279
- * }
2280
- * ```
2281
- */
2282
- async checkServerTrustStatus(serverId, userAddress) {
2283
- try {
2284
- const user = userAddress ?? this.context.userAddress;
2285
- const trustedServers = await this.getTrustedServers(user);
2286
- const trustIndex = trustedServers.findIndex(
2287
- (server) => server === serverId
2288
- );
2289
- return {
2290
- serverId,
2291
- isTrusted: trustIndex !== -1,
2292
- trustIndex: trustIndex !== -1 ? trustIndex : void 0
2293
- };
2294
- } catch (error) {
2295
- throw new BlockchainError(
2296
- `Failed to check server trust status: ${error instanceof Error ? error.message : "Unknown error"}`,
2297
- error
2298
- );
2299
- }
2300
- }
2301
- /**
2302
- * Composes EIP-712 typed data for AddAndTrustServer.
2303
- *
2304
- * @remarks
2305
- * Creates the complete typed data structure required for EIP-712 signature generation
2306
- * when adding and trusting a new server in a single transaction.
2307
- *
2308
- * @param input - The add and trust server input data containing server details
2309
- * @returns Promise resolving to the typed data structure for server add and trust
2310
- */
2311
- async composeAddAndTrustServerMessage(input) {
2312
- const domain = await this.getServersDomain();
2313
- console.debug(domain);
2314
- return {
2315
- domain,
2316
- types: {
2317
- AddServer: [
2318
- { name: "nonce", type: "uint256" },
2319
- { name: "serverAddress", type: "address" },
2320
- { name: "publicKey", type: "string" },
2321
- { name: "serverUrl", type: "string" }
2322
- ]
2323
- },
2324
- primaryType: "AddServer",
2325
- message: input
2326
- };
2327
- }
2328
- /**
2329
- * Composes EIP-712 typed data for TrustServer.
2330
- *
2331
- * @param input - The trust server input data containing server details
2332
- * @returns Promise resolving to the typed data structure for server trust
2333
- */
2334
- async composeTrustServerMessage(input) {
2335
- const domain = await this.getServersDomain();
2336
- return {
2337
- domain,
2338
- types: {
2339
- TrustServer: [
2340
- { name: "nonce", type: "uint256" },
2341
- { name: "serverId", type: "uint256" }
2342
- ]
2343
- },
2344
- primaryType: "TrustServer",
2345
- message: input
2346
- };
2347
- }
2348
- /**
2349
- * Composes EIP-712 typed data for UntrustServer.
2350
- *
2351
- * @param input - The untrust server input data containing server details
2352
- * @returns Promise resolving to the typed data structure for server untrust
2353
- */
2354
- async composeUntrustServerMessage(input) {
2355
- const domain = await this.getServersDomain();
2356
- return {
2357
- domain,
2358
- types: {
2359
- UntrustServer: [
2360
- { name: "nonce", type: "uint256" },
2361
- { name: "serverId", type: "uint256" }
2362
- ]
2363
- },
2364
- primaryType: "UntrustServer",
2365
- message: input
2366
- };
2367
- }
2368
- /**
2369
- * Gets the EIP-712 domain for DataPortabilityServers signatures.
2370
- *
2371
- * @returns Promise resolving to the EIP-712 domain configuration
2372
- */
2373
- async getServersDomain() {
2374
- const chainId = await this.context.publicClient.getChainId();
2375
- const DataPortabilityServersAddress = getContractAddress(
2376
- chainId,
2377
- "DataPortabilityServers"
2378
- );
2379
- return {
2380
- name: "VanaDataPortabilityServers",
2381
- version: "1",
2382
- chainId,
2383
- verifyingContract: DataPortabilityServersAddress
2384
- };
2385
- }
2386
- /**
2387
- * Submits an add and trust server transaction directly to the blockchain.
2388
- *
2389
- * @param addAndTrustServerInput - The add and trust server input data containing server details
2390
- * @param signature - The cryptographic signature for the transaction
2391
- * @returns Promise resolving to the transaction hash
2392
- */
2393
- async submitAddAndTrustServerTransaction(addAndTrustServerInput, signature, options) {
2394
- this.assertWallet();
2395
- const chainId = await this.context.walletClient.getChainId();
2396
- const DataPortabilityServersAddress = getContractAddress(
2397
- chainId,
2398
- "DataPortabilityServers"
2399
- );
2400
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2401
- console.debug("\u{1F50D} Transaction Debug Info:", {
2402
- chainId,
2403
- contractAddress: DataPortabilityServersAddress,
2404
- input: {
2405
- nonce: addAndTrustServerInput.nonce.toString(),
2406
- serverAddress: addAndTrustServerInput.serverAddress,
2407
- publicKey: addAndTrustServerInput.publicKey,
2408
- serverUrl: addAndTrustServerInput.serverUrl
2409
- },
2410
- signature
2411
- });
2412
- const formattedSignature = formatSignatureForContract(signature);
2413
- const txHash = await this.context.walletClient.writeContract({
2414
- address: DataPortabilityServersAddress,
2415
- abi: DataPortabilityServersAbi,
2416
- functionName: "addAndTrustServerWithSignature",
2417
- args: [
2418
- {
2419
- nonce: addAndTrustServerInput.nonce,
2420
- serverAddress: addAndTrustServerInput.serverAddress,
2421
- publicKey: addAndTrustServerInput.publicKey,
2422
- serverUrl: addAndTrustServerInput.serverUrl
2423
- },
2424
- formattedSignature
2425
- ],
2426
- account: this.context.walletClient?.account ?? this.context.userAddress,
2427
- chain: this.context.walletClient?.chain ?? null,
2428
- ...options && {
2429
- gas: options.gas,
2430
- nonce: options.nonce,
2431
- // Use EIP-1559 gas pricing if available, otherwise legacy
2432
- ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2433
- maxFeePerGas: options.maxFeePerGas,
2434
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
2435
- } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2436
- }
2437
- });
2438
- return txHash;
2439
- }
2440
- /**
2441
- * Submits a trust server transaction directly to the blockchain.
2442
- *
2443
- * @param trustServerInput - The trust server input data containing server details
2444
- * @param signature - The cryptographic signature for the transaction
2445
- * @returns Promise resolving to the transaction hash
2446
- */
2447
- async submitTrustServerTransaction(trustServerInput, signature, options) {
2448
- this.assertWallet();
2449
- const chainId = await this.context.walletClient.getChainId();
2450
- const DataPortabilityServersAddress = getContractAddress(
2451
- chainId,
2452
- "DataPortabilityServers"
2453
- );
2454
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2455
- const formattedSignature = formatSignatureForContract(signature);
2456
- const txHash = await this.context.walletClient.writeContract({
2457
- address: DataPortabilityServersAddress,
2458
- abi: DataPortabilityServersAbi,
2459
- functionName: "trustServerWithSignature",
2460
- args: [
2461
- {
2462
- nonce: trustServerInput.nonce,
2463
- serverId: BigInt(trustServerInput.serverId)
2464
- },
2465
- formattedSignature
2466
- ],
2467
- account: this.context.walletClient?.account ?? this.context.userAddress,
2468
- chain: this.context.walletClient?.chain ?? null,
2469
- ...this.spreadTransactionOptions(options)
2470
- });
2471
- return txHash;
2472
- }
2473
- /**
2474
- * Submits a revoke transaction directly to the blockchain with signature.
2475
- *
2476
- * @param typedData - The EIP-712 typed data structure for the revoke operation
2477
- * @param signature - The cryptographic signature authorizing the revoke
2478
- * @returns Promise resolving to the transaction hash
2479
- */
2480
- async submitDirectRevokeTransaction(typedData, signature, options) {
2481
- this.assertWallet();
2482
- const chainId = await this.context.walletClient.getChainId();
2483
- const DataPortabilityPermissionsAddress = getContractAddress(
2484
- chainId,
2485
- "DataPortabilityPermissions"
2486
- );
2487
- const DataPortabilityPermissionsAbi = getAbi("DataPortabilityPermissions");
2488
- const formattedSignature = formatSignatureForContract(signature);
2489
- const txHash = await this.context.walletClient.writeContract({
2490
- address: DataPortabilityPermissionsAddress,
2491
- abi: DataPortabilityPermissionsAbi,
2492
- functionName: "revokePermissionWithSignature",
2493
- args: [typedData.message, formattedSignature],
2494
- account: this.context.walletClient?.account ?? this.context.userAddress,
2495
- chain: this.context.walletClient?.chain ?? null,
2496
- ...options && {
2497
- gas: options.gas,
2498
- nonce: options.nonce,
2499
- // Use EIP-1559 gas pricing if available, otherwise legacy
2500
- ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2501
- maxFeePerGas: options.maxFeePerGas,
2502
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
2503
- } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2504
- }
2505
- });
2506
- return txHash;
2507
- }
2508
- /**
2509
- * Submits an untrust server transaction with signature.
2510
- *
2511
- * @param typedData - The EIP-712 typed data structure for the untrust operation
2512
- * @param signature - The cryptographic signature authorizing the untrust
2513
- * @returns Promise resolving to the transaction hash
2514
- */
2515
- async submitSignedUntrustTransaction(typedData, signature, options) {
2516
- this.assertWallet();
2517
- const chainId = await this.context.walletClient.getChainId();
2518
- const DataPortabilityServersAddress = getContractAddress(
2519
- chainId,
2520
- "DataPortabilityServers"
2521
- );
2522
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2523
- const formattedSignature = formatSignatureForContract(signature);
2524
- const contractMessage = {
2525
- nonce: typedData.message.nonce,
2526
- serverId: BigInt(typedData.message.serverId)
2527
- };
2528
- const txHash = await this.context.walletClient.writeContract({
2529
- address: DataPortabilityServersAddress,
2530
- abi: DataPortabilityServersAbi,
2531
- functionName: "untrustServerWithSignature",
2532
- args: [contractMessage, formattedSignature],
2533
- account: this.context.walletClient?.account ?? this.context.userAddress,
2534
- chain: this.context.walletClient?.chain ?? null,
2535
- ...options && {
2536
- gas: options.gas,
2537
- nonce: options.nonce,
2538
- // Use EIP-1559 gas pricing if available, otherwise legacy
2539
- ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2540
- maxFeePerGas: options.maxFeePerGas,
2541
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
2542
- } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2543
- }
2544
- });
2545
- return txHash;
2546
- }
2547
- // ===========================
2548
- // GRANTEE METHODS
2549
- // ===========================
2550
- /**
2551
- * Registers a new grantee in the DataPortabilityGrantees contract.
2552
- *
2553
- * A grantee is an entity (like an application) that can receive data permissions
2554
- * from users. Once registered, users can grant the grantee access to their data.
2555
- *
2556
- * This method supports gasless transactions via relayer when configured.
2557
- * If no relayer is available, it falls back to direct wallet transactions.
2558
- *
2559
- * @param params - Parameters for registering the grantee
2560
- * @param params.owner - The Ethereum address that will own this grantee registration
2561
- * @param params.granteeAddress - The Ethereum address of the grantee (application)
2562
- * @param params.publicKey - The public key used for data encryption/decryption (hex string)
2563
- * @param options - Optional transaction options for gas parameters and timeout
2564
- * @returns Promise resolving to the transaction hash
2565
- * @throws {BlockchainError} When the grantee registration transaction fails
2566
- * @throws {UserRejectedRequestError} When user rejects the transaction
2567
- * @throws {RelayerError} When gasless transaction submission fails
2568
- *
2569
- * @example
2570
- * ```typescript
2571
- * const txHash = await vana.permissions.registerGrantee({
2572
- * owner: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
2573
- * granteeAddress: "0xApp1234567890123456789012345678901234567890",
2574
- * publicKey: "0x1234567890abcdef..."
2575
- * });
2576
- * console.log(`Grantee registered in transaction: ${txHash}`);
2577
- * ```
2578
- */
2579
- async submitRegisterGrantee(params, options) {
2580
- try {
2581
- let hash;
2582
- if (this.context.relayer) {
2583
- const request = {
2584
- type: "direct",
2585
- operation: "submitRegisterGrantee",
2586
- params: {
2587
- owner: params.owner,
2588
- granteeAddress: params.granteeAddress,
2589
- publicKey: params.publicKey
2590
- }
2591
- };
2592
- const response = await this.context.relayer(request);
2593
- if (response.type === "error") {
2594
- throw new RelayerError(response.error);
2595
- }
2596
- if (response.type === "submitted") {
2597
- hash = response.hash;
2598
- } else if (response.type === "direct") {
2599
- const result = response.result;
2600
- hash = result.transactionHash;
2601
- } else {
2602
- throw new Error("Unexpected response type from relayer");
2603
- }
2604
- } else {
2605
- this.assertWallet();
2606
- const chainId = await this.context.walletClient.getChainId();
2607
- const DataPortabilityGranteesAddress = getContractAddress(
2608
- chainId,
2609
- "DataPortabilityGrantees"
2610
- );
2611
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
2612
- const ownerAddress = getAddress(params.owner);
2613
- const granteeAddress = getAddress(params.granteeAddress);
2614
- const account2 = this.context.walletClient?.account ?? this.context.userAddress;
2615
- hash = await this.context.walletClient.writeContract({
2616
- address: DataPortabilityGranteesAddress,
2617
- abi: DataPortabilityGranteesAbi,
2618
- functionName: "registerGrantee",
2619
- args: [ownerAddress, granteeAddress, params.publicKey],
2620
- account: account2,
2621
- chain: this.context.walletClient?.chain ?? null,
2622
- ...this.spreadTransactionOptions(options)
2623
- });
2624
- }
2625
- const account = this.context.walletClient?.account ?? this.context.userAddress;
2626
- const { tx } = await import("../utils/transactionHelpers");
2627
- return tx({
2628
- hash,
2629
- from: typeof account === "string" ? account : account.address,
2630
- contract: "DataPortabilityGrantees",
2631
- fn: "registerGrantee"
2632
- });
2633
- } catch (error) {
2634
- if (error instanceof Error) {
2635
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof BlockchainError) {
2636
- throw error;
2637
- }
2638
- if (error.name === "ContractFunctionExecutionError") {
2639
- throw new BlockchainError(
2640
- `Grantee registration failed: ${error.message}`,
2641
- error
2642
- );
2643
- }
2644
- if (error.name === "UserRejectedRequestError") {
2645
- throw new UserRejectedRequestError(
2646
- "User rejected the grantee registration transaction"
2647
- );
2648
- }
2649
- throw new BlockchainError(
2650
- `Failed to register grantee: ${error.message}`,
2651
- error
2652
- );
2653
- }
2654
- throw new BlockchainError(`Failed to register grantee: ${String(error)}`);
2655
- }
2656
- }
2657
- // TODO: When DataPortabilityGrantees contract adds registerGranteeWithSignature function,
2658
- // implement submitRegisterGranteeWithSignature and submitSignedRegisterGrantee methods
2659
- // to support EIP-712 signed gasless transactions via relayer.
2660
- // Current implementation above supports direct gasless transactions (relayer pays gas directly).
2661
- /**
2662
- * Retrieves all registered grantees from the DataPortabilityGrantees contract.
2663
- *
2664
- * Returns a paginated list of all grantees (applications) that have been registered
2665
- * in the system and can receive data permissions from users.
2666
- *
2667
- * @param options - Query options for pagination and filtering
2668
- * @param options.limit - Maximum number of grantees to return (default: 50)
2669
- * @param options.offset - Number of grantees to skip for pagination (default: 0)
2670
- * @returns Promise resolving to paginated grantees with metadata
2671
- * @throws {BlockchainError} When contract read operation fails
2672
- * @throws {NetworkError} When unable to connect to the blockchain network
2673
- *
2674
- * @example
2675
- * ```typescript
2676
- * // Get first 10 grantees
2677
- * const result = await vana.permissions.getGrantees({
2678
- * limit: 10,
2679
- * offset: 0
2680
- * });
2681
- *
2682
- * console.log(`Found ${result.total} total grantees`);
2683
- * result.grantees.forEach(grantee => {
2684
- * console.log(`Grantee ${grantee.id}: ${grantee.granteeAddress}`);
2685
- * });
2686
- *
2687
- * // Check if there are more results
2688
- * if (result.hasMore) {
2689
- * console.log('More grantees available');
2690
- * }
2691
- * ```
2692
- */
2693
- async getGrantees(options = {}) {
2694
- const chainId = await this.context.publicClient.getChainId();
2695
- const DataPortabilityGranteesAddress = getContractAddress(
2696
- chainId,
2697
- "DataPortabilityGrantees"
2698
- );
2699
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
2700
- const totalCount = await this.context.publicClient.readContract({
2701
- address: DataPortabilityGranteesAddress,
2702
- abi: DataPortabilityGranteesAbi,
2703
- functionName: "granteesCount"
2704
- });
2705
- const total = Number(totalCount);
2706
- const limit = options.limit ?? 50;
2707
- const offset = options.offset ?? 0;
2708
- const includePermissions = options.includePermissions ?? true;
2709
- const startId = total - offset;
2710
- const endId = Math.max(startId - limit + 1, 1);
2711
- const granteeIds = Array.from(
2712
- { length: startId - endId + 1 },
2713
- (_, i) => startId - i
2714
- // Generate IDs in descending order
2715
- );
2716
- let grantees;
2717
- if (includePermissions) {
2718
- const granteePromises = granteeIds.map(
2719
- (granteeId) => this.getGranteeById(granteeId)
2720
- );
2721
- const granteeResults = await Promise.all(granteePromises);
2722
- grantees = granteeResults.filter(
2723
- (grantee) => grantee !== null
2724
- );
2725
- } else {
2726
- const granteeInfoPromises = granteeIds.map(
2727
- async (granteeId) => {
2728
- try {
2729
- const granteeInfo = await this.context.publicClient.readContract({
2730
- address: DataPortabilityGranteesAddress,
2731
- abi: DataPortabilityGranteesAbi,
2732
- functionName: "granteesV2",
2733
- args: [BigInt(granteeId)]
2734
- });
2735
- const grantee = {
2736
- id: granteeId,
2737
- owner: granteeInfo.owner,
2738
- address: granteeInfo.granteeAddress,
2739
- publicKey: granteeInfo.publicKey,
2740
- permissionIds: []
2741
- // TypeScript infers number[] from Grantee type
2742
- };
2743
- return grantee;
2744
- } catch (error) {
2745
- console.warn(`Failed to fetch grantee ${granteeId}:`, error);
2746
- return null;
2747
- }
2748
- }
2749
- );
2750
- const granteeInfoResults = await Promise.all(granteeInfoPromises);
2751
- grantees = granteeInfoResults.filter(
2752
- (grantee) => grantee !== null
2753
- );
2754
- }
2755
- return {
2756
- grantees,
2757
- total,
2758
- offset,
2759
- limit,
2760
- hasMore: offset + limit < total
2761
- };
2762
- }
2763
- /**
2764
- * Retrieves a specific grantee by their Ethereum wallet address.
2765
- *
2766
- * @remarks
2767
- * Looks up a registered grantee (application) using their Ethereum address
2768
- * and returns their complete registration information including all associated permissions.
2769
- *
2770
- * Returns `null` if the address is not registered as a grantee or if an error occurs.
2771
- *
2772
- * @param granteeAddress - Ethereum wallet address of the grantee to query
2773
- * @returns Grantee information including ID, addresses, public key, and permission IDs, or `null` if not found
2774
- *
2775
- * @example
2776
- * ```typescript
2777
- * const granteeAddress = "0xApp1234567890123456789012345678901234567890";
2778
- * const grantee = await vana.permissions.getGranteeByAddress(granteeAddress);
2779
- *
2780
- * if (grantee) {
2781
- * console.log(`Found grantee ${grantee.id}`);
2782
- * console.log(`Owner: ${grantee.owner}`);
2783
- * console.log(`Public Key: ${grantee.publicKey}`);
2784
- * console.log(`Permissions: ${grantee.permissionIds.join(', ')}`);
2785
- * } else {
2786
- * console.log('Grantee not found');
2787
- * }
2788
- * ```
2789
- */
2790
- async getGranteeByAddress(granteeAddress) {
2791
- const chainId = await this.context.publicClient.getChainId();
2792
- const DataPortabilityGranteesAddress = getContractAddress(
2793
- chainId,
2794
- "DataPortabilityGrantees"
2795
- );
2796
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
2797
- try {
2798
- const granteeId = await this.context.publicClient.readContract({
2799
- address: DataPortabilityGranteesAddress,
2800
- abi: DataPortabilityGranteesAbi,
2801
- functionName: "granteeAddressToId",
2802
- args: [granteeAddress]
2803
- });
2804
- if (granteeId === 0n) {
2805
- return null;
2806
- }
2807
- return await this.getGranteeById(Number(granteeId));
2808
- } catch (error) {
2809
- console.warn(`Failed to fetch grantee ${granteeAddress}:`, error);
2810
- return null;
2811
- }
2812
- }
2813
- /**
2814
- * Retrieves a specific grantee by their unique ID.
2815
- *
2816
- * @remarks
2817
- * Looks up a registered grantee (application) using their numeric ID assigned during
2818
- * registration and returns their complete information including all associated permissions.
2819
- *
2820
- * Returns `null` if the grantee is not found or if an error occurs during fetching.
2821
- *
2822
- * @param granteeId - Unique numeric ID of the grantee (1-indexed)
2823
- * @returns Grantee information including ID, addresses, public key, and permission IDs, or `null` if not found
2824
- *
2825
- * @example
2826
- * ```typescript
2827
- * const grantee = await vana.permissions.getGranteeById(1);
2828
- *
2829
- * if (grantee) {
2830
- * console.log(`Grantee ID: ${grantee.id}`);
2831
- * console.log(`Address: ${grantee.address}`);
2832
- * console.log(`Owner: ${grantee.owner}`);
2833
- * console.log(`Total permissions: ${grantee.permissionIds.length}`);
2834
- * } else {
2835
- * console.log('Grantee with ID 1 not found');
2836
- * }
2837
- * ```
2838
- */
2839
- async getGranteeById(granteeId) {
2840
- const chainId = await this.context.publicClient.getChainId();
2841
- const DataPortabilityGranteesAddress = getContractAddress(
2842
- chainId,
2843
- "DataPortabilityGrantees"
2844
- );
2845
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
2846
- try {
2847
- const granteeInfoResult = await this.context.publicClient.readContract({
2848
- address: DataPortabilityGranteesAddress,
2849
- abi: DataPortabilityGranteesAbi,
2850
- functionName: "granteesV2",
2851
- args: [BigInt(granteeId)]
2852
- });
2853
- const granteeInfo = granteeInfoResult;
2854
- const allPermissionIdsResult = await this.getGranteePermissionsPaginated(
2855
- BigInt(granteeId)
2856
- );
2857
- const allPermissionIds = allPermissionIdsResult;
2858
- return {
2859
- id: granteeId,
2860
- owner: granteeInfo.owner,
2861
- address: granteeInfo.granteeAddress,
2862
- publicKey: granteeInfo.publicKey,
2863
- permissionIds: allPermissionIds.map((id) => Number(id))
2864
- };
2865
- } catch (error) {
2866
- console.warn(`Failed to fetch grantee ${granteeId}:`, error);
2867
- return null;
2868
- }
2869
- }
2870
- // ===========================
2871
- // DATA PORTABILITY SERVERS HELPER METHODS
2872
- // ===========================
2873
- /**
2874
- * Get all trusted server IDs for a user
2875
- *
2876
- * @param userAddress - User address to query (defaults to current user)
2877
- * @returns Promise resolving to array of server IDs
2878
- */
2879
- async getUserServerIds(userAddress) {
2880
- try {
2881
- const targetAddress = userAddress ?? this.context.userAddress;
2882
- const chainId = await this.context.publicClient.getChainId();
2883
- const DataPortabilityServersAddress = getContractAddress(
2884
- chainId,
2885
- "DataPortabilityServers"
2886
- );
2887
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2888
- const serverIds = await this.context.publicClient.readContract({
2889
- address: DataPortabilityServersAddress,
2890
- abi: DataPortabilityServersAbi,
2891
- functionName: "userServerIdsValues",
2892
- args: [targetAddress]
2893
- });
2894
- return [...serverIds];
2895
- } catch (error) {
2896
- throw new BlockchainError(
2897
- `Failed to get user server IDs: ${error instanceof Error ? error.message : "Unknown error"}`,
2898
- error
2899
- );
2900
- }
2901
- }
2902
- /**
2903
- * Get server ID at specific index for a user
2904
- *
2905
- * @param userAddress - User address to query
2906
- * @param serverIndex - Index in the user's server list
2907
- * @returns Promise resolving to server ID
2908
- */
2909
- async getUserServerIdAt(userAddress, serverIndex) {
2910
- try {
2911
- const chainId = await this.context.publicClient.getChainId();
2912
- const DataPortabilityServersAddress = getContractAddress(
2913
- chainId,
2914
- "DataPortabilityServers"
2915
- );
2916
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2917
- const serverId = await this.context.publicClient.readContract({
2918
- address: DataPortabilityServersAddress,
2919
- abi: DataPortabilityServersAbi,
2920
- functionName: "userServerIdsAt",
2921
- args: [userAddress, serverIndex]
2922
- });
2923
- return serverId;
2924
- } catch (error) {
2925
- throw new BlockchainError(
2926
- `Failed to get user server ID at index: ${error instanceof Error ? error.message : "Unknown error"}`,
2927
- error
2928
- );
2929
- }
2930
- }
2931
- /**
2932
- * Get the number of trusted servers for a user
2933
- *
2934
- * @param userAddress - User address to query (defaults to current user)
2935
- * @returns Promise resolving to number of trusted servers
2936
- */
2937
- async getUserServerCount(userAddress) {
2938
- try {
2939
- const targetAddress = userAddress ?? this.context.userAddress;
2940
- const chainId = await this.context.publicClient.getChainId();
2941
- const DataPortabilityServersAddress = getContractAddress(
2942
- chainId,
2943
- "DataPortabilityServers"
2944
- );
2945
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2946
- const count = await this.context.publicClient.readContract({
2947
- address: DataPortabilityServersAddress,
2948
- abi: DataPortabilityServersAbi,
2949
- functionName: "userServerIdsLength",
2950
- args: [targetAddress]
2951
- });
2952
- return count;
2953
- } catch (error) {
2954
- throw new BlockchainError(
2955
- `Failed to get user server count: ${error instanceof Error ? error.message : "Unknown error"}`,
2956
- error
2957
- );
2958
- }
2959
- }
2960
- /**
2961
- * Get detailed information about trusted servers for a user
2962
- *
2963
- * @param userAddress - User address to query (defaults to current user)
2964
- * @returns Promise resolving to array of trusted server info
2965
- */
2966
- async getUserTrustedServers(userAddress) {
2967
- try {
2968
- const targetAddress = userAddress ?? this.context.userAddress;
2969
- const chainId = await this.context.publicClient.getChainId();
2970
- const DataPortabilityServersAddress = getContractAddress(
2971
- chainId,
2972
- "DataPortabilityServers"
2973
- );
2974
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
2975
- const servers = await this.context.publicClient.readContract({
2976
- address: DataPortabilityServersAddress,
2977
- abi: DataPortabilityServersAbi,
2978
- functionName: "userServerValues",
2979
- args: [targetAddress]
2980
- });
2981
- return [...servers];
2982
- } catch (error) {
2983
- throw new BlockchainError(
2984
- `Failed to get user trusted servers: ${error instanceof Error ? error.message : "Unknown error"}`,
2985
- error
2986
- );
2987
- }
2988
- }
2989
- /**
2990
- * Get trusted server info for a specific server ID and user
2991
- *
2992
- * @param userAddress - User address to query
2993
- * @param serverId - Server ID to get info for
2994
- * @returns Promise resolving to trusted server info
2995
- */
2996
- async getUserTrustedServer(userAddress, serverId) {
2997
- try {
2998
- const chainId = await this.context.publicClient.getChainId();
2999
- const DataPortabilityServersAddress = getContractAddress(
3000
- chainId,
3001
- "DataPortabilityServers"
3002
- );
3003
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3004
- const serverInfo = await this.context.publicClient.readContract({
3005
- address: DataPortabilityServersAddress,
3006
- abi: DataPortabilityServersAbi,
3007
- functionName: "userServers",
3008
- args: [userAddress, serverId]
3009
- });
3010
- return serverInfo;
3011
- } catch (error) {
3012
- throw new BlockchainError(
3013
- `Failed to get user trusted server: ${error instanceof Error ? error.message : "Unknown error"}`,
3014
- error
3015
- );
3016
- }
3017
- }
3018
- /**
3019
- * Get server information by server ID
3020
- *
3021
- * @param serverId - Server ID to get info for
3022
- * @returns Promise resolving to server info
3023
- */
3024
- async getServerInfo(serverId) {
3025
- try {
3026
- const chainId = await this.context.publicClient.getChainId();
3027
- const DataPortabilityServersAddress = getContractAddress(
3028
- chainId,
3029
- "DataPortabilityServers"
3030
- );
3031
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3032
- const serverInfo = await this.context.publicClient.readContract({
3033
- address: DataPortabilityServersAddress,
3034
- abi: DataPortabilityServersAbi,
3035
- functionName: "servers",
3036
- args: [serverId]
3037
- });
3038
- return serverInfo;
3039
- } catch (error) {
3040
- throw new BlockchainError(
3041
- `Failed to get server info: ${error instanceof Error ? error.message : "Unknown error"}`,
3042
- error
3043
- );
3044
- }
3045
- }
3046
- /**
3047
- * Get server information by server address
3048
- *
3049
- * @param serverAddress - Server address to get info for
3050
- * @returns Promise resolving to server info
3051
- */
3052
- async getServerInfoByAddress(serverAddress) {
3053
- try {
3054
- const chainId = await this.context.publicClient.getChainId();
3055
- const DataPortabilityServersAddress = getContractAddress(
3056
- chainId,
3057
- "DataPortabilityServers"
3058
- );
3059
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3060
- const serverInfo = await this.context.publicClient.readContract({
3061
- address: DataPortabilityServersAddress,
3062
- abi: DataPortabilityServersAbi,
3063
- functionName: "serverByAddress",
3064
- args: [serverAddress]
3065
- });
3066
- return serverInfo;
3067
- } catch (error) {
3068
- throw new BlockchainError(
3069
- `Failed to get server info by address: ${error instanceof Error ? error.message : "Unknown error"}`,
3070
- error
3071
- );
3072
- }
3073
- }
3074
- // ===========================
3075
- // DATA PORTABILITY PERMISSIONS HELPER METHODS
3076
- // ===========================
3077
- /**
3078
- * Get all permission IDs for a user
3079
- *
3080
- * @param userAddress - User address to query (defaults to current user)
3081
- * @returns Promise resolving to array of permission IDs
3082
- */
3083
- async getUserPermissionIds(userAddress) {
3084
- try {
3085
- const targetAddress = userAddress ?? this.context.userAddress;
3086
- const chainId = await this.context.publicClient.getChainId();
3087
- const DataPortabilityPermissionsAddress = getContractAddress(
3088
- chainId,
3089
- "DataPortabilityPermissions"
3090
- );
3091
- const DataPortabilityPermissionsAbi = getAbi(
3092
- "DataPortabilityPermissions"
3093
- );
3094
- const permissionIds = await this.context.publicClient.readContract({
3095
- address: DataPortabilityPermissionsAddress,
3096
- abi: DataPortabilityPermissionsAbi,
3097
- functionName: "userPermissionIdsValues",
3098
- args: [targetAddress]
3099
- });
3100
- return [...permissionIds];
3101
- } catch (error) {
3102
- throw new BlockchainError(
3103
- `Failed to get user permission IDs: ${error instanceof Error ? error.message : "Unknown error"}`,
3104
- error
3105
- );
3106
- }
3107
- }
3108
- /**
3109
- * Get permission ID at specific index for a user
3110
- *
3111
- * @param userAddress - User address to query
3112
- * @param permissionIndex - Index in the user's permission list
3113
- * @returns Promise resolving to permission ID
3114
- */
3115
- async getUserPermissionIdAt(userAddress, permissionIndex) {
3116
- try {
3117
- const chainId = await this.context.publicClient.getChainId();
3118
- const DataPortabilityPermissionsAddress = getContractAddress(
3119
- chainId,
3120
- "DataPortabilityPermissions"
3121
- );
3122
- const DataPortabilityPermissionsAbi = getAbi(
3123
- "DataPortabilityPermissions"
3124
- );
3125
- const permissionId = await this.context.publicClient.readContract({
3126
- address: DataPortabilityPermissionsAddress,
3127
- abi: DataPortabilityPermissionsAbi,
3128
- functionName: "userPermissionIdsAt",
3129
- args: [userAddress, permissionIndex]
3130
- });
3131
- return permissionId;
3132
- } catch (error) {
3133
- throw new BlockchainError(
3134
- `Failed to get user permission ID at index: ${error instanceof Error ? error.message : "Unknown error"}`,
3135
- error
3136
- );
3137
- }
3138
- }
3139
- /**
3140
- * Get the number of permissions for a user
3141
- *
3142
- * @param userAddress - User address to query (defaults to current user)
3143
- * @returns Promise resolving to number of permissions
3144
- */
3145
- async getUserPermissionCount(userAddress) {
3146
- try {
3147
- const targetAddress = userAddress ?? this.context.userAddress;
3148
- const chainId = await this.context.publicClient.getChainId();
3149
- const DataPortabilityPermissionsAddress = getContractAddress(
3150
- chainId,
3151
- "DataPortabilityPermissions"
3152
- );
3153
- const DataPortabilityPermissionsAbi = getAbi(
3154
- "DataPortabilityPermissions"
3155
- );
3156
- const count = await this.context.publicClient.readContract({
3157
- address: DataPortabilityPermissionsAddress,
3158
- abi: DataPortabilityPermissionsAbi,
3159
- functionName: "userPermissionIdsLength",
3160
- args: [targetAddress]
3161
- });
3162
- return count;
3163
- } catch (error) {
3164
- throw new BlockchainError(
3165
- `Failed to get user permission count: ${error instanceof Error ? error.message : "Unknown error"}`,
3166
- error
3167
- );
3168
- }
3169
- }
3170
- /**
3171
- * Get detailed permission information by permission ID
3172
- *
3173
- * @param permissionId - Permission ID to get info for
3174
- * @returns Promise resolving to permission info
3175
- */
3176
- async getPermissionInfo(permissionId) {
3177
- try {
3178
- const chainId = await this.context.publicClient.getChainId();
3179
- const DataPortabilityPermissionsAddress = getContractAddress(
3180
- chainId,
3181
- "DataPortabilityPermissions"
3182
- );
3183
- const DataPortabilityPermissionsAbi = getAbi(
3184
- "DataPortabilityPermissions"
3185
- );
3186
- const permissionInfo = await this.context.publicClient.readContract({
3187
- address: DataPortabilityPermissionsAddress,
3188
- abi: DataPortabilityPermissionsAbi,
3189
- functionName: "permissions",
3190
- args: [permissionId]
3191
- });
3192
- return permissionInfo;
3193
- } catch (error) {
3194
- throw new BlockchainError(
3195
- `Failed to get permission info: ${error instanceof Error ? error.message : "Unknown error"}`,
3196
- error
3197
- );
3198
- }
3199
- }
3200
- /**
3201
- * Get all permission IDs for a specific file
3202
- *
3203
- * @param fileId - File ID to get permissions for
3204
- * @returns Promise resolving to array of permission IDs
3205
- */
3206
- async getFilePermissionIds(fileId) {
3207
- try {
3208
- const chainId = await this.context.publicClient.getChainId();
3209
- const DataPortabilityPermissionsAddress = getContractAddress(
3210
- chainId,
3211
- "DataPortabilityPermissions"
3212
- );
3213
- const DataPortabilityPermissionsAbi = getAbi(
3214
- "DataPortabilityPermissions"
3215
- );
3216
- const permissionIds = await this.context.publicClient.readContract({
3217
- address: DataPortabilityPermissionsAddress,
3218
- abi: DataPortabilityPermissionsAbi,
3219
- functionName: "filePermissionIds",
3220
- args: [fileId]
3221
- });
3222
- return [...permissionIds];
3223
- } catch (error) {
3224
- throw new BlockchainError(
3225
- `Failed to get file permission IDs: ${error instanceof Error ? error.message : "Unknown error"}`,
3226
- error
3227
- );
3228
- }
3229
- }
3230
- /**
3231
- * Get all file IDs for a specific permission
3232
- *
3233
- * @param permissionId - Permission ID to get files for
3234
- * @returns Promise resolving to array of file IDs
3235
- */
3236
- async getPermissionFileIds(permissionId) {
3237
- try {
3238
- const chainId = await this.context.publicClient.getChainId();
3239
- const DataPortabilityPermissionsAddress = getContractAddress(
3240
- chainId,
3241
- "DataPortabilityPermissions"
3242
- );
3243
- const DataPortabilityPermissionsAbi = getAbi(
3244
- "DataPortabilityPermissions"
3245
- );
3246
- const fileIds = await this.context.publicClient.readContract({
3247
- address: DataPortabilityPermissionsAddress,
3248
- abi: DataPortabilityPermissionsAbi,
3249
- functionName: "permissionFileIds",
3250
- args: [permissionId]
3251
- });
3252
- return [...fileIds];
3253
- } catch (error) {
3254
- throw new BlockchainError(
3255
- `Failed to get permission file IDs: ${error instanceof Error ? error.message : "Unknown error"}`,
3256
- error
3257
- );
3258
- }
3259
- }
3260
- /**
3261
- * Retrieves detailed grant file data from IPFS or HTTP storage.
3262
- *
3263
- * @remarks
3264
- * This method automatically uses the SDK's configured downloadRelayer to bypass CORS restrictions.
3265
- * Use this instead of importing the standalone `retrieveGrantFile` utility.
3266
- *
3267
- * @param grantUrl - The grant file URL (from OnChainPermissionGrant.grantUrl)
3268
- * @returns Promise resolving to the complete grant file with operation details
3269
- * @throws {NetworkError} When all retrieval attempts fail
3270
- * @example
3271
- * ```typescript
3272
- * const grants = await vana.permissions.getUserPermissionGrantsOnChain();
3273
- * const grantFile = await vana.permissions.retrieveGrantFile(grants[0].grantUrl);
3274
- * console.log(`Operation: ${grantFile.operation}`);
3275
- * ```
3276
- */
3277
- async retrieveGrantFile(grantUrl) {
3278
- const { retrieveGrantFile: retrieveGrantFileUtil } = await import("../utils/grantFiles");
3279
- return retrieveGrantFileUtil(
3280
- grantUrl,
3281
- void 0,
3282
- this.context.downloadRelayer
3283
- );
3284
- }
3285
- /**
3286
- * Get all permissions for a specific file (alias for getFilePermissionIds)
3287
- *
3288
- * @param fileId - File ID to get permissions for
3289
- * @returns Promise resolving to array of permission IDs
3290
- */
3291
- async getFilePermissions(fileId) {
3292
- const chainId = await this.context.publicClient.getChainId();
3293
- const DataPortabilityPermissionsAddress = getContractAddress(
3294
- chainId,
3295
- "DataPortabilityPermissions"
3296
- );
3297
- const DataPortabilityPermissionsAbi = getAbi("DataPortabilityPermissions");
3298
- const permissions = await this.context.publicClient.readContract({
3299
- address: DataPortabilityPermissionsAddress,
3300
- abi: DataPortabilityPermissionsAbi,
3301
- functionName: "filePermissions",
3302
- args: [fileId]
3303
- });
3304
- return [...permissions];
3305
- }
3306
- // ===========================
3307
- // DATA PORTABILITY GRANTEES HELPER METHODS
3308
- // ===========================
3309
- /**
3310
- * Retrieves detailed grantee information including all associated permissions.
3311
- *
3312
- * @remarks
3313
- * Returns grantee metadata and associated permission IDs. Uses the newer
3314
- * paginated contract method internally for efficient permission fetching.
3315
- *
3316
- * @param granteeId - Unique grantee identifier as bigint
3317
- * @returns Grantee information containing owner address, grantee address, public key, and permission IDs
3318
- * @throws {BlockchainError} When grantee ID is not found or contract read fails
3319
- *
3320
- * @example
3321
- * ```typescript
3322
- * const granteeInfo = await vana.permissions.getGranteeInfo(BigInt(1));
3323
- * console.log(`Grantee ${granteeInfo.granteeAddress} has ${granteeInfo.permissionIds.length} permissions`);
3324
- * ```
3325
- */
3326
- async getGranteeInfo(granteeId) {
3327
- try {
3328
- const grantee = await this.getGranteeById(Number(granteeId));
3329
- if (!grantee) {
3330
- throw new Error("Grantee not found");
3331
- }
3332
- return {
3333
- owner: grantee.owner,
3334
- granteeAddress: grantee.address,
3335
- publicKey: grantee.publicKey,
3336
- permissionIds: grantee.permissionIds.map((id) => BigInt(id))
3337
- };
3338
- } catch (error) {
3339
- throw new BlockchainError(
3340
- `Failed to get grantee info: ${error instanceof Error ? error.message : "Unknown error"}`,
3341
- error
3342
- );
3343
- }
3344
- }
3345
- /**
3346
- * Retrieves detailed grantee information by wallet address.
3347
- *
3348
- * @remarks
3349
- * Looks up the grantee ID from the provided address, then fetches complete
3350
- * grantee information including all associated permissions.
3351
- *
3352
- * @param granteeAddress - Ethereum wallet address of the grantee to query
3353
- * @returns Grantee information containing owner address, grantee address, public key, and permission IDs
3354
- * @throws {BlockchainError} When grantee address is not registered or contract read fails
3355
- *
3356
- * @example
3357
- * ```typescript
3358
- * const granteeInfo = await vana.permissions.getGranteeInfoByAddress("0x742d35Cc6634c0532925a3b844Bc9e8e1ee3b2De");
3359
- * console.log(`Found grantee with ${granteeInfo.permissionIds.length} permissions`);
3360
- * ```
3361
- */
3362
- async getGranteeInfoByAddress(granteeAddress) {
3363
- try {
3364
- const chainId = await this.context.publicClient.getChainId();
3365
- const DataPortabilityGranteesAddress = getContractAddress(
3366
- chainId,
3367
- "DataPortabilityGrantees"
3368
- );
3369
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
3370
- const granteeIdResult = await this.context.publicClient.readContract({
3371
- address: DataPortabilityGranteesAddress,
3372
- abi: DataPortabilityGranteesAbi,
3373
- functionName: "granteeAddressToId",
3374
- args: [granteeAddress]
3375
- });
3376
- const granteeId = granteeIdResult;
3377
- if (granteeId === 0n) {
3378
- throw new Error("Grantee not found");
3379
- }
3380
- const grantee = await this.getGranteeById(Number(granteeId));
3381
- if (!grantee) {
3382
- throw new Error("Grantee not found");
3383
- }
3384
- return {
3385
- owner: grantee.owner,
3386
- granteeAddress: grantee.address,
3387
- publicKey: grantee.publicKey,
3388
- permissionIds: grantee.permissionIds.map((id) => BigInt(id))
3389
- };
3390
- } catch (error) {
3391
- throw new BlockchainError(
3392
- `Failed to get grantee info by address: ${error instanceof Error ? error.message : "Unknown error"}`,
3393
- error
3394
- );
3395
- }
3396
- }
3397
- /**
3398
- * Get all permission IDs for a specific grantee
3399
- *
3400
- * @param granteeId - Grantee ID to get permissions for
3401
- * @returns Promise resolving to array of permission IDs
3402
- */
3403
- async getGranteePermissionIds(granteeId) {
3404
- try {
3405
- const chainId = await this.context.publicClient.getChainId();
3406
- const DataPortabilityGranteesAddress = getContractAddress(
3407
- chainId,
3408
- "DataPortabilityGrantees"
3409
- );
3410
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
3411
- const permissionIds = await this.context.publicClient.readContract({
3412
- address: DataPortabilityGranteesAddress,
3413
- abi: DataPortabilityGranteesAbi,
3414
- functionName: "granteePermissionIds",
3415
- args: [granteeId]
3416
- });
3417
- return [...permissionIds];
3418
- } catch (error) {
3419
- throw new BlockchainError(
3420
- `Failed to get grantee permission IDs: ${error instanceof Error ? error.message : "Unknown error"}`,
3421
- error
3422
- );
3423
- }
3424
- }
3425
- /**
3426
- * Get all permissions for a specific grantee (alias for getGranteePermissionIds)
3427
- *
3428
- * @param granteeId - Grantee ID to get permissions for
3429
- * @returns Promise resolving to array of permission IDs
3430
- */
3431
- async getGranteePermissions(granteeId) {
3432
- try {
3433
- const chainId = await this.context.publicClient.getChainId();
3434
- const DataPortabilityGranteesAddress = getContractAddress(
3435
- chainId,
3436
- "DataPortabilityGrantees"
3437
- );
3438
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
3439
- const permissions = await this.context.publicClient.readContract({
3440
- address: DataPortabilityGranteesAddress,
3441
- abi: DataPortabilityGranteesAbi,
3442
- functionName: "granteePermissions",
3443
- args: [granteeId]
3444
- });
3445
- return [...permissions];
3446
- } catch (error) {
3447
- throw new BlockchainError(
3448
- `Failed to get grantee permissions: ${error instanceof Error ? error.message : "Unknown error"}`,
3449
- error
3450
- );
3451
- }
3452
- }
3453
- /**
3454
- * Retrieves permission IDs for a specific grantee with flexible pagination.
3455
- *
3456
- * @remarks
3457
- * **Pagination Behavior:**
3458
- * Returns different types based on parameters:
3459
- * - Without offset/limit: Returns `bigint[]` of all permissions using batched multicall
3460
- * - With offset/limit: Returns paginated object with `permissionIds`, `totalCount`, and `hasMore`
3461
- *
3462
- * Uses gas-aware multicall for efficient batch fetching when retrieving all permissions.
3463
- *
3464
- * @param granteeId - Grantee ID to get permissions for
3465
- * @param options - Optional pagination parameters
3466
- * @param options.offset - Zero-based starting index for pagination. Defaults to 0 when fetching all permissions. Required for single-page requests.
3467
- * @param options.limit - Maximum number of permission IDs to return per page. Defaults to 100 when fetching all permissions. Required for single-page requests.
3468
- * @returns When called without options: Array of all permission IDs as `bigint[]`.
3469
- * When called with offset and limit: Paginated result object containing `permissionIds` array,
3470
- * `totalCount`, and `hasMore` boolean.
3471
- * @throws {BlockchainError} When contract read operation fails
3472
- *
3473
- * @example
3474
- * ```typescript
3475
- * // Fetch all permissions (no pagination params)
3476
- * const allPermissions = await vana.permissions.getGranteePermissionsPaginated(BigInt(1));
3477
- * console.log(`Total permissions: ${allPermissions.length}`);
3478
- *
3479
- * // Fetch a specific page (with pagination params)
3480
- * const page = await vana.permissions.getGranteePermissionsPaginated(BigInt(1), {
3481
- * offset: BigInt(0),
3482
- * limit: BigInt(100)
3483
- * });
3484
- * console.log(`Fetched ${page.permissionIds.length} permissions`);
3485
- * console.log(`Total: ${page.totalCount}, Has more: ${page.hasMore}`);
3486
- *
3487
- * // Fetch next page
3488
- * if (page.hasMore) {
3489
- * const nextPage = await vana.permissions.getGranteePermissionsPaginated(BigInt(1), {
3490
- * offset: BigInt(100),
3491
- * limit: BigInt(100)
3492
- * });
3493
- * }
3494
- * ```
3495
- */
3496
- async getGranteePermissionsPaginated(granteeId, options) {
3497
- try {
3498
- const chainId = await this.context.publicClient.getChainId();
3499
- const DataPortabilityGranteesAddress = getContractAddress(
3500
- chainId,
3501
- "DataPortabilityGrantees"
3502
- );
3503
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
3504
- const fetchOnlyOnePage = options?.offset !== void 0 && options?.limit !== void 0;
3505
- if (fetchOnlyOnePage) {
3506
- const result = await this.context.publicClient.readContract({
3507
- address: DataPortabilityGranteesAddress,
3508
- abi: DataPortabilityGranteesAbi,
3509
- functionName: "granteePermissionsPaginated",
3510
- args: [granteeId, options.offset, options.limit]
3511
- });
3512
- const [permissionIds, totalCount2, hasMore] = result;
3513
- return {
3514
- permissionIds: [...permissionIds],
3515
- totalCount: totalCount2,
3516
- hasMore
3517
- };
3518
- }
3519
- const countResult = await this.context.publicClient.readContract({
3520
- address: DataPortabilityGranteesAddress,
3521
- abi: DataPortabilityGranteesAbi,
3522
- functionName: "granteePermissionsPaginated",
3523
- args: [granteeId, BigInt(0), BigInt(1)]
3524
- });
3525
- const [, totalCount] = countResult;
3526
- if (totalCount === BigInt(0)) {
3527
- return [];
3528
- }
3529
- const batchSize = options?.limit ?? BigInt(100);
3530
- const startOffset = options?.offset ?? BigInt(0);
3531
- const endOffset = totalCount;
3532
- const numBatches = Math.ceil(
3533
- Number(endOffset - startOffset) / Number(batchSize)
3534
- );
3535
- const paginationCalls = Array.from({ length: numBatches }, (_, i) => ({
3536
- address: DataPortabilityGranteesAddress,
3537
- abi: DataPortabilityGranteesAbi,
3538
- functionName: "granteePermissionsPaginated",
3539
- args: [
3540
- granteeId,
3541
- startOffset + BigInt(i) * batchSize,
3542
- batchSize
3543
- ]
3544
- }));
3545
- const results = await gasAwareMulticall(
3546
- this.context.publicClient,
3547
- {
3548
- contracts: paginationCalls
3549
- }
3550
- );
3551
- const allPermissionIds = [];
3552
- for (const result of results) {
3553
- const [permissionIds] = result;
3554
- allPermissionIds.push(...permissionIds);
3555
- }
3556
- return allPermissionIds;
3557
- } catch (error) {
3558
- throw new BlockchainError(
3559
- `Failed to get grantee permissions: ${error instanceof Error ? error.message : "Unknown error"}`,
3560
- error
3561
- );
3562
- }
3563
- }
3564
- // ===== DataPortabilityServersImplementation Methods =====
3565
- /**
3566
- * Get all server IDs for a user
3567
- *
3568
- * @param userAddress - User address to get server IDs for
3569
- * @returns Promise resolving to array of server IDs
3570
- */
3571
- async getUserServerIdsValues(userAddress) {
3572
- try {
3573
- const chainId = await this.context.publicClient.getChainId();
3574
- const DataPortabilityServersAddress = getContractAddress(
3575
- chainId,
3576
- "DataPortabilityServers"
3577
- );
3578
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3579
- const serverIds = await this.context.publicClient.readContract({
3580
- address: DataPortabilityServersAddress,
3581
- abi: DataPortabilityServersAbi,
3582
- functionName: "userServerIdsValues",
3583
- args: [userAddress]
3584
- });
3585
- return [...serverIds];
3586
- } catch (error) {
3587
- throw new BlockchainError(
3588
- `Failed to get user server IDs: ${error instanceof Error ? error.message : "Unknown error"}`,
3589
- error
3590
- );
3591
- }
3592
- }
3593
- /**
3594
- * Get server ID at specific index for a user
3595
- *
3596
- * @param userAddress - User address
3597
- * @param serverIndex - Index of the server ID
3598
- * @returns Promise resolving to server ID
3599
- */
3600
- async getUserServerIdsAt(userAddress, serverIndex) {
3601
- try {
3602
- const chainId = await this.context.publicClient.getChainId();
3603
- const DataPortabilityServersAddress = getContractAddress(
3604
- chainId,
3605
- "DataPortabilityServers"
3606
- );
3607
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3608
- const serverId = await this.context.publicClient.readContract({
3609
- address: DataPortabilityServersAddress,
3610
- abi: DataPortabilityServersAbi,
3611
- functionName: "userServerIdsAt",
3612
- args: [userAddress, serverIndex]
3613
- });
3614
- return serverId;
3615
- } catch (error) {
3616
- throw new BlockchainError(
3617
- `Failed to get user server ID at index: ${error instanceof Error ? error.message : "Unknown error"}`,
3618
- error
3619
- );
3620
- }
3621
- }
3622
- /**
3623
- * Get the number of servers a user has
3624
- *
3625
- * @param userAddress - User address
3626
- * @returns Promise resolving to number of servers
3627
- */
3628
- async getUserServerIdsLength(userAddress) {
3629
- try {
3630
- const chainId = await this.context.publicClient.getChainId();
3631
- const DataPortabilityServersAddress = getContractAddress(
3632
- chainId,
3633
- "DataPortabilityServers"
3634
- );
3635
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3636
- const length = await this.context.publicClient.readContract({
3637
- address: DataPortabilityServersAddress,
3638
- abi: DataPortabilityServersAbi,
3639
- functionName: "userServerIdsLength",
3640
- args: [userAddress]
3641
- });
3642
- return length;
3643
- } catch (error) {
3644
- throw new BlockchainError(
3645
- `Failed to get user server IDs length: ${error instanceof Error ? error.message : "Unknown error"}`,
3646
- error
3647
- );
3648
- }
3649
- }
3650
- /**
3651
- * Get trusted server info for a specific user and server ID
3652
- *
3653
- * @param userAddress - User address
3654
- * @param serverId - Server ID
3655
- * @returns Promise resolving to trusted server info
3656
- */
3657
- async getUserServers(userAddress, serverId) {
3658
- try {
3659
- const chainId = await this.context.publicClient.getChainId();
3660
- const DataPortabilityServersAddress = getContractAddress(
3661
- chainId,
3662
- "DataPortabilityServers"
3663
- );
3664
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3665
- const serverInfo = await this.context.publicClient.readContract({
3666
- address: DataPortabilityServersAddress,
3667
- abi: DataPortabilityServersAbi,
3668
- functionName: "userServers",
3669
- args: [userAddress, serverId]
3670
- });
3671
- return {
3672
- id: serverInfo.id,
3673
- owner: serverInfo.owner,
3674
- serverAddress: serverInfo.serverAddress,
3675
- publicKey: serverInfo.publicKey,
3676
- url: serverInfo.url,
3677
- startBlock: serverInfo.startBlock,
3678
- endBlock: serverInfo.endBlock
3679
- };
3680
- } catch (error) {
3681
- throw new BlockchainError(
3682
- `Failed to get user server info: ${error instanceof Error ? error.message : "Unknown error"}`,
3683
- error
3684
- );
3685
- }
3686
- }
3687
- /**
3688
- * Get server info by server ID
3689
- *
3690
- * @param serverId - Server ID
3691
- * @returns Promise resolving to server info
3692
- */
3693
- async getServers(serverId) {
3694
- try {
3695
- const chainId = await this.context.publicClient.getChainId();
3696
- const DataPortabilityServersAddress = getContractAddress(
3697
- chainId,
3698
- "DataPortabilityServers"
3699
- );
3700
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3701
- const serverInfo = await this.context.publicClient.readContract({
3702
- address: DataPortabilityServersAddress,
3703
- abi: DataPortabilityServersAbi,
3704
- functionName: "servers",
3705
- args: [serverId]
3706
- });
3707
- return {
3708
- id: serverInfo.id,
3709
- owner: serverInfo.owner,
3710
- serverAddress: serverInfo.serverAddress,
3711
- publicKey: serverInfo.publicKey,
3712
- url: serverInfo.url
3713
- };
3714
- } catch (error) {
3715
- throw new BlockchainError(
3716
- `Failed to get server info: ${error instanceof Error ? error.message : "Unknown error"}`,
3717
- error
3718
- );
3719
- }
3720
- }
3721
- /**
3722
- * Get user info including nonce and trusted server IDs
3723
- *
3724
- * @param userAddress - User address
3725
- * @returns Promise resolving to user info
3726
- */
3727
- async getUsers(userAddress) {
3728
- try {
3729
- const chainId = await this.context.publicClient.getChainId();
3730
- const DataPortabilityServersAddress = getContractAddress(
3731
- chainId,
3732
- "DataPortabilityServers"
3733
- );
3734
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3735
- const userInfo = await this.context.publicClient.readContract({
3736
- address: DataPortabilityServersAddress,
3737
- abi: DataPortabilityServersAbi,
3738
- functionName: "users",
3739
- args: [userAddress]
3740
- });
3741
- return {
3742
- nonce: userInfo[0],
3743
- trustedServerIds: [...userInfo[1]]
3744
- };
3745
- } catch (error) {
3746
- throw new BlockchainError(
3747
- `Failed to get user info: ${error instanceof Error ? error.message : "Unknown error"}`,
3748
- error
3749
- );
3750
- }
3751
- }
3752
- /**
3753
- * Update server URL
3754
- *
3755
- * @param serverId - Server ID to update
3756
- * @param url - New URL for the server
3757
- * @param options - Optional transaction options for gas parameters and timeout
3758
- * @returns Promise resolving to transaction hash
3759
- */
3760
- async submitUpdateServer(serverId, url, options) {
3761
- this.assertWallet();
3762
- try {
3763
- const chainId = await this.context.walletClient.getChainId();
3764
- const DataPortabilityServersAddress = getContractAddress(
3765
- chainId,
3766
- "DataPortabilityServers"
3767
- );
3768
- const DataPortabilityServersAbi = getAbi("DataPortabilityServers");
3769
- const account = this.context.walletClient?.account ?? this.context.userAddress;
3770
- const hash = await this.context.walletClient.writeContract({
3771
- address: DataPortabilityServersAddress,
3772
- abi: DataPortabilityServersAbi,
3773
- functionName: "updateServer",
3774
- args: [serverId, url],
3775
- chain: this.context.walletClient?.chain,
3776
- account,
3777
- ...options?.gas && { gas: options.gas },
3778
- ...options?.nonce && { nonce: options.nonce },
3779
- // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
3780
- ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
3781
- ...options.maxFeePerGas && {
3782
- maxFeePerGas: options.maxFeePerGas
3783
- },
3784
- ...options.maxPriorityFeePerGas && {
3785
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
3786
- }
3787
- } : options?.gasPrice && { gasPrice: options.gasPrice }
3788
- });
3789
- const { tx } = await import("../utils/transactionHelpers");
3790
- return tx({
3791
- hash,
3792
- from: typeof account === "string" ? account : account.address,
3793
- contract: "DataPortabilityServers",
3794
- fn: "updateServer"
3795
- });
3796
- } catch (error) {
3797
- throw new BlockchainError(
3798
- `Failed to update server: ${error instanceof Error ? error.message : "Unknown error"}`,
3799
- error
3800
- );
3801
- }
3802
- }
3803
- // ===== DataPortabilityPermissionsImplementation Methods =====
3804
- /**
3805
- * Get all permission IDs for a user
3806
- *
3807
- * @param userAddress - User address to get permission IDs for
3808
- * @returns Promise resolving to array of permission IDs
3809
- */
3810
- async getUserPermissionIdsValues(userAddress) {
3811
- try {
3812
- const chainId = await this.context.publicClient.getChainId();
3813
- const DataPortabilityPermissionsAddress = getContractAddress(
3814
- chainId,
3815
- "DataPortabilityPermissions"
3816
- );
3817
- const DataPortabilityPermissionsAbi = getAbi(
3818
- "DataPortabilityPermissions"
3819
- );
3820
- const permissionIds = await this.context.publicClient.readContract({
3821
- address: DataPortabilityPermissionsAddress,
3822
- abi: DataPortabilityPermissionsAbi,
3823
- functionName: "userPermissionIdsValues",
3824
- args: [userAddress]
3825
- });
3826
- return [...permissionIds];
3827
- } catch (error) {
3828
- throw new BlockchainError(
3829
- `Failed to get user permission IDs: ${error instanceof Error ? error.message : "Unknown error"}`,
3830
- error
3831
- );
3832
- }
3833
- }
3834
- /**
3835
- * Get permission ID at specific index for a user
3836
- *
3837
- * @param userAddress - User address
3838
- * @param permissionIndex - Index of the permission ID
3839
- * @returns Promise resolving to permission ID
3840
- */
3841
- async getUserPermissionIdsAt(userAddress, permissionIndex) {
3842
- try {
3843
- const chainId = await this.context.publicClient.getChainId();
3844
- const DataPortabilityPermissionsAddress = getContractAddress(
3845
- chainId,
3846
- "DataPortabilityPermissions"
3847
- );
3848
- const DataPortabilityPermissionsAbi = getAbi(
3849
- "DataPortabilityPermissions"
3850
- );
3851
- const permissionId = await this.context.publicClient.readContract({
3852
- address: DataPortabilityPermissionsAddress,
3853
- abi: DataPortabilityPermissionsAbi,
3854
- functionName: "userPermissionIdsAt",
3855
- args: [userAddress, permissionIndex]
3856
- });
3857
- return permissionId;
3858
- } catch (error) {
3859
- throw new BlockchainError(
3860
- `Failed to get user permission ID at index: ${error instanceof Error ? error.message : "Unknown error"}`,
3861
- error
3862
- );
3863
- }
3864
- }
3865
- /**
3866
- * Get the number of permissions a user has
3867
- *
3868
- * @param userAddress - User address
3869
- * @returns Promise resolving to number of permissions
3870
- */
3871
- async getUserPermissionIdsLength(userAddress) {
3872
- try {
3873
- const chainId = await this.context.publicClient.getChainId();
3874
- const DataPortabilityPermissionsAddress = getContractAddress(
3875
- chainId,
3876
- "DataPortabilityPermissions"
3877
- );
3878
- const DataPortabilityPermissionsAbi = getAbi(
3879
- "DataPortabilityPermissions"
3880
- );
3881
- const length = await this.context.publicClient.readContract({
3882
- address: DataPortabilityPermissionsAddress,
3883
- abi: DataPortabilityPermissionsAbi,
3884
- functionName: "userPermissionIdsLength",
3885
- args: [userAddress]
3886
- });
3887
- return length;
3888
- } catch (error) {
3889
- throw new BlockchainError(
3890
- `Failed to get user permission IDs length: ${error instanceof Error ? error.message : "Unknown error"}`,
3891
- error
3892
- );
3893
- }
3894
- }
3895
- /**
3896
- * Get permission info by permission ID
3897
- *
3898
- * @param permissionId - Permission ID
3899
- * @returns Promise resolving to permission info
3900
- */
3901
- async getPermissions(permissionId) {
3902
- try {
3903
- const chainId = await this.context.publicClient.getChainId();
3904
- const DataPortabilityPermissionsAddress = getContractAddress(
3905
- chainId,
3906
- "DataPortabilityPermissions"
3907
- );
3908
- const DataPortabilityPermissionsAbi = getAbi(
3909
- "DataPortabilityPermissions"
3910
- );
3911
- const permissionInfo = await this.context.publicClient.readContract({
3912
- address: DataPortabilityPermissionsAddress,
3913
- abi: DataPortabilityPermissionsAbi,
3914
- functionName: "permissions",
3915
- args: [permissionId]
3916
- });
3917
- return {
3918
- id: permissionInfo.id,
3919
- grantor: permissionInfo.grantor,
3920
- nonce: permissionInfo.nonce,
3921
- granteeId: permissionInfo.granteeId,
3922
- grant: permissionInfo.grant,
3923
- startBlock: permissionInfo.startBlock,
3924
- endBlock: permissionInfo.endBlock,
3925
- fileIds: [...permissionInfo.fileIds]
3926
- };
3927
- } catch (error) {
3928
- throw new BlockchainError(
3929
- `Failed to get permission info: ${error instanceof Error ? error.message : "Unknown error"}`,
3930
- error
3931
- );
3932
- }
3933
- }
3934
- /**
3935
- * Submit permission with signature to the blockchain (supports gasless transactions)
3936
- *
3937
- * @param params - Parameters for adding permission
3938
- * @returns Promise resolving to transaction hash
3939
- * @throws {RelayerError} When gasless transaction submission fails
3940
- * @throws {SignatureError} When user rejects the signature request
3941
- * @throws {BlockchainError} When permission addition fails
3942
- * @throws {NetworkError} When network communication fails
3943
- */
3944
- async submitAddPermission(params) {
3945
- this.assertWallet();
3946
- try {
3947
- const nonce = await this.getPermissionsUserNonce();
3948
- const addPermissionInput = {
3949
- nonce,
3950
- granteeId: params.granteeId,
3951
- grant: params.grant,
3952
- fileUrls: params.fileUrls,
3953
- schemaIds: params.schemaIds,
3954
- serverAddress: params.serverAddress,
3955
- serverUrl: params.serverUrl,
3956
- serverPublicKey: params.serverPublicKey,
3957
- filePermissions: params.filePermissions
3958
- };
3959
- const typedData = await this.composeServerFilesAndPermissionMessage(addPermissionInput);
3960
- const signature = await this.signTypedData(typedData);
3961
- return await this.submitSignedAddPermission(typedData, signature);
3962
- } catch (error) {
3963
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
3964
- throw error;
3965
- }
3966
- throw new BlockchainError(
3967
- `Failed to add permission: ${error instanceof Error ? error.message : "Unknown error"}`,
3968
- error
3969
- );
3970
- }
3971
- }
3972
- /**
3973
- * Submits an already-signed add permission transaction to the blockchain.
3974
- * This method supports both relayer-based gasless transactions and direct transactions.
3975
- *
3976
- * @param typedData - The EIP-712 typed data for AddPermission
3977
- * @param signature - The user's signature
3978
- * @returns Promise resolving to TransactionResult with PermissionGrantResult event data
3979
- * @throws {RelayerError} When gasless transaction submission fails
3980
- * @throws {BlockchainError} When permission addition fails
3981
- * @throws {NetworkError} When network communication fails
3982
- */
3983
- async submitSignedAddPermission(typedData, signature, options) {
3984
- this.assertWallet();
3985
- try {
3986
- let hash;
3987
- if (this.context.relayer) {
3988
- const request = {
3989
- type: "signed",
3990
- operation: "submitAddPermission",
3991
- typedData,
3992
- signature
3993
- };
3994
- const response = await this.context.relayer(request);
3995
- if (response.type === "error") {
3996
- throw new RelayerError(response.error);
3997
- }
3998
- if (response.type === "submitted") {
3999
- hash = response.hash;
4000
- } else if (response.type === "signed") {
4001
- hash = response.hash;
4002
- } else {
4003
- throw new Error("Unexpected response type from relayer");
4004
- }
4005
- } else {
4006
- hash = await this.submitDirectAddPermissionTransaction(
4007
- typedData,
4008
- signature,
4009
- options
4010
- );
4011
- }
4012
- const account = this.context.walletClient?.account ?? this.context.userAddress;
4013
- const { tx } = await import("../utils/transactionHelpers");
4014
- return tx({
4015
- hash,
4016
- from: typeof account === "string" ? account : account.address,
4017
- contract: "DataPortabilityPermissions",
4018
- fn: "addPermission"
4019
- });
4020
- } catch (error) {
4021
- if (error instanceof RelayerError || error instanceof NetworkError || error instanceof UserRejectedRequestError || error instanceof SignatureError || error instanceof NonceError) {
4022
- throw error;
4023
- }
4024
- throw new BlockchainError(
4025
- `Add permission submission failed: ${error instanceof Error ? error.message : "Unknown error"}`,
4026
- error
4027
- );
4028
- }
4029
- }
4030
- /**
4031
- * Submits server files and permissions with signature to the blockchain, supporting schema validation and gasless transactions.
4032
- *
4033
- * @remarks
4034
- * This method validates files against their specified schemas before submission.
4035
- * Schema validation ensures data conforms to expected formats before on-chain registration.
4036
- * Files with schemaId = 0 bypass validation. The method supports atomic batch operations
4037
- * where all files and permissions are registered in a single transaction.
4038
- *
4039
- * @param params - Parameters for adding server files and permissions
4040
- * @param params.granteeId - The ID of the permission grantee
4041
- * @param params.grant - Grant URL containing permission parameters (typically IPFS)
4042
- * @param params.fileUrls - Array of file URLs to register
4043
- * @param params.schemaIds - Schema IDs for each file. Use 0 for files without schema validation.
4044
- * Array length must match fileUrls length.
4045
- * @param params.serverAddress - Server wallet address for decryption permissions
4046
- * @param params.serverUrl - Server endpoint URL
4047
- * @param params.serverPublicKey - Server's public key for encryption.
4048
- * Obtain via `vana.server.getIdentity(userAddress).publicKey`.
4049
- * @param params.filePermissions - Nested array of permissions for each file
4050
- * @param options - Optional transaction options for gas parameters and timeout.
4051
- * Note: These options are only applied for direct blockchain transactions.
4052
- * When using relayer callbacks (gasless transactions), these options are ignored.
4053
- * @returns TransactionResult with immediate hash access and optional event data
4054
- * @throws {Error} When schemaIds array length doesn't match fileUrls array length
4055
- * @throws {SchemaValidationError} When file data doesn't match the specified schema.
4056
- * Verify data structure matches schema definition from `vana.schemas.get(schemaId)`.
4057
- * @throws {RelayerError} When gasless transaction submission fails.
4058
- * Retry without relayer configuration to submit direct transaction.
4059
- * @throws {SignatureError} When user rejects the signature request
4060
- * @throws {BlockchainError} When server files and permissions addition fails
4061
- * @throws {NetworkError} When network communication fails.
4062
- * Check network connection or configure alternative gateways.
4063
- *
4064
- * @example
4065
- * ```typescript
4066
- * // Submit with custom gas parameters and timeout
4067
- * const result = await vana.permissions.submitAddServerFilesAndPermissions({
4068
- * granteeId: BigInt(1),
4069
- * grant: "ipfs://QmXxx...",
4070
- * fileUrls: ["https://storage.example.com/data.json"],
4071
- * schemaIds: [123], // LinkedIn profile schema ID
4072
- * serverAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0b0Bb",
4073
- * serverUrl: "https://server.example.com",
4074
- * serverPublicKey: serverInfo.publicKey,
4075
- * filePermissions: [[{
4076
- * account: "0x742d35Cc6634C0532925a3b844Bc9e7595f0b0Bb",
4077
- * key: encryptedKey
4078
- * }]]
4079
- * }, {
4080
- * maxFeePerGas: 100n * 10n ** 9n, // 100 gwei
4081
- * maxPriorityFeePerGas: 2n * 10n ** 9n, // 2 gwei tip
4082
- * });
4083
- *
4084
- * // Wait for confirmation with custom timeout
4085
- * const receipt = await vana.waitForTransactionReceipt(result, {
4086
- * timeout: 180000 // 3 minutes
4087
- * });
4088
- * console.log(`Transaction confirmed: ${receipt.transactionHash}`);
4089
- * ```
4090
- */
4091
- async submitAddServerFilesAndPermissions(params, options) {
4092
- this.assertWallet();
4093
- try {
4094
- if (params.schemaIds.length !== params.fileUrls.length) {
4095
- throw new Error(
4096
- `schemaIds array length (${params.schemaIds.length}) must match fileUrls array length (${params.fileUrls.length})`
4097
- );
4098
- }
4099
- const nonce = await this.getPermissionsUserNonce();
4100
- const serverFilesAndPermissionInput = {
4101
- nonce,
4102
- granteeId: params.granteeId,
4103
- grant: params.grant,
4104
- fileUrls: params.fileUrls,
4105
- schemaIds: params.schemaIds,
4106
- serverAddress: params.serverAddress,
4107
- serverUrl: params.serverUrl,
4108
- serverPublicKey: params.serverPublicKey,
4109
- filePermissions: params.filePermissions
4110
- };
4111
- const typedData = await this.composeServerFilesAndPermissionMessage(
4112
- serverFilesAndPermissionInput
4113
- );
4114
- const signature = await this.signTypedData(typedData);
4115
- return await this.submitSignedAddServerFilesAndPermissions(
4116
- typedData,
4117
- signature,
4118
- options
4119
- );
4120
- } catch (error) {
4121
- if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
4122
- throw error;
4123
- }
4124
- throw new BlockchainError(
4125
- `Failed to add server files and permissions: ${error instanceof Error ? error.message : "Unknown error"}`,
4126
- error
4127
- );
4128
- }
4129
- }
4130
- /**
4131
- * Submits an already-signed add server files and permissions transaction to the blockchain.
4132
- *
4133
- * @remarks
4134
- * This method returns a TransactionResult that provides immediate access to the transaction hash.
4135
- * The eventData field may contain parsed event details after transaction confirmation.
4136
- *
4137
- * @param typedData - The EIP-712 typed data for AddServerFilesAndPermissions
4138
- * @param signature - The user's signature
4139
- * @param options - Optional transaction options for gas parameters and timeout.
4140
- * Note: These options are only applied for direct blockchain transactions.
4141
- * When using relayer callbacks (gasless transactions), these options are ignored.
4142
- * @returns TransactionResult with immediate hash access and optional event data
4143
- * @throws {RelayerError} When gasless transaction submission fails
4144
- * @throws {BlockchainError} When server files and permissions addition fails
4145
- * @throws {NetworkError} When network communication fails
4146
- *
4147
- * @example
4148
- * ```typescript
4149
- * const tx = await vana.permissions.submitSignedAddServerFilesAndPermissions(
4150
- * typedData,
4151
- * signature
4152
- * );
4153
- * console.log(`Transaction submitted: ${tx.hash}`);
4154
- *
4155
- * // Wait for confirmation and get the permission ID
4156
- * const { permissionId } = await tx.waitForEvents();
4157
- * console.log(`Permission created with ID: ${permissionId}`);
4158
- * ```
4159
- */
4160
- async submitSignedAddServerFilesAndPermissions(typedData, signature, options) {
4161
- this.assertWallet();
4162
- try {
4163
- let hash;
4164
- if (this.context.relayer) {
4165
- console.debug(
4166
- "\u{1F680} Using relayer for submitAddServerFilesAndPermissions"
4167
- );
4168
- const request = {
4169
- type: "signed",
4170
- operation: "submitAddServerFilesAndPermissions",
4171
- typedData,
4172
- signature
4173
- };
4174
- const response = await this.context.relayer(request);
4175
- if (response.type === "error") {
4176
- throw new RelayerError(response.error);
4177
- }
4178
- if (response.type === "submitted") {
4179
- hash = response.hash;
4180
- } else if (response.type === "signed") {
4181
- hash = response.hash;
4182
- } else {
4183
- throw new Error("Unexpected response type from relayer");
4184
- }
4185
- } else {
4186
- console.debug(
4187
- "\u{1F4DD} Using direct transaction for submitAddServerFilesAndPermissions"
4188
- );
4189
- hash = await this.submitDirectAddServerFilesAndPermissionsTransaction(
4190
- typedData,
4191
- signature,
4192
- options
4193
- );
4194
- }
4195
- const account = this.context.walletClient?.account ?? this.context.userAddress;
4196
- const { tx } = await import("../utils/transactionHelpers");
4197
- return tx({
4198
- hash,
4199
- from: typeof account === "string" ? account : account.address,
4200
- contract: "DataPortabilityPermissions",
4201
- fn: "addServerFilesAndPermissions"
4202
- });
4203
- } catch (error) {
4204
- if (error instanceof RelayerError || error instanceof NetworkError || error instanceof UserRejectedRequestError || error instanceof SignatureError || error instanceof NonceError) {
4205
- throw error;
4206
- }
4207
- throw new BlockchainError(
4208
- `Add server files and permissions submission failed: ${error instanceof Error ? error.message : "Unknown error"}`,
4209
- error
4210
- );
4211
- }
4212
- }
4213
- /**
4214
- * Submit permission revocation with signature to the blockchain
4215
- *
4216
- * @param permissionId - Permission ID to revoke
4217
- * @param options - Optional transaction options for gas parameters and timeout
4218
- * @returns Promise resolving to transaction hash
4219
- */
4220
- async submitRevokePermission(permissionId, options) {
4221
- this.assertWallet();
4222
- try {
4223
- const chainId = await this.context.walletClient.getChainId();
4224
- const DataPortabilityPermissionsAddress = getContractAddress(
4225
- chainId,
4226
- "DataPortabilityPermissions"
4227
- );
4228
- const DataPortabilityPermissionsAbi = getAbi(
4229
- "DataPortabilityPermissions"
4230
- );
4231
- const { account } = this.context.walletClient;
4232
- if (!account) {
4233
- throw new Error("No wallet account connected");
4234
- }
4235
- const hash = await this.context.walletClient.writeContract({
4236
- address: DataPortabilityPermissionsAddress,
4237
- abi: DataPortabilityPermissionsAbi,
4238
- functionName: "revokePermission",
4239
- args: [permissionId],
4240
- chain: this.context.walletClient?.chain,
4241
- account,
4242
- ...options?.gas && { gas: options.gas },
4243
- ...options?.nonce && { nonce: options.nonce },
4244
- // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
4245
- ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
4246
- ...options.maxFeePerGas && {
4247
- maxFeePerGas: options.maxFeePerGas
4248
- },
4249
- ...options.maxPriorityFeePerGas && {
4250
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
4251
- }
4252
- } : options?.gasPrice && { gasPrice: options.gasPrice }
4253
- });
4254
- const { tx } = await import("../utils/transactionHelpers");
4255
- return tx({
4256
- hash,
4257
- from: typeof account === "string" ? account : account.address,
4258
- contract: "DataPortabilityPermissions",
4259
- fn: "revokePermission"
4260
- });
4261
- } catch (error) {
4262
- throw new BlockchainError(
4263
- `Failed to revoke permission: ${error instanceof Error ? error.message : "Unknown error"}`,
4264
- error
4265
- );
4266
- }
4267
- }
4268
- /**
4269
- * Submits a signed add permission transaction directly to the blockchain.
4270
- *
4271
- * @param typedData - The typed data structure for the permission addition
4272
- * @param signature - The cryptographic signature authorizing the transaction
4273
- * @returns Promise resolving to the transaction hash
4274
- */
4275
- async submitDirectAddPermissionTransaction(typedData, signature, options) {
4276
- this.assertWallet();
4277
- const chainId = await this.context.walletClient.getChainId();
4278
- const DataPortabilityPermissionsAddress = getContractAddress(
4279
- chainId,
4280
- "DataPortabilityPermissions"
4281
- );
4282
- const DataPortabilityPermissionsAbi = getAbi("DataPortabilityPermissions");
4283
- const permissionInput = {
4284
- nonce: typedData.message.nonce,
4285
- granteeId: typedData.message.granteeId,
4286
- grant: typedData.message.grant,
4287
- fileIds: typedData.message.fileIds ?? []
4288
- };
4289
- const formattedSignature = formatSignatureForContract(signature);
4290
- const hash = await this.context.walletClient.writeContract({
4291
- address: DataPortabilityPermissionsAddress,
4292
- abi: DataPortabilityPermissionsAbi,
4293
- functionName: "addPermission",
4294
- args: [permissionInput, formattedSignature],
4295
- account: this.context.walletClient?.account ?? this.context.userAddress,
4296
- chain: this.context.walletClient?.chain ?? null,
4297
- ...this.spreadTransactionOptions(options)
4298
- });
4299
- return hash;
4300
- }
4301
- /**
4302
- * Submits a signed add server files and permissions transaction directly to the blockchain.
4303
- *
4304
- * @param typedData - The typed data structure for the server files and permissions addition
4305
- * @param signature - The cryptographic signature authorizing the transaction
4306
- * @returns Promise resolving to the transaction hash
4307
- */
4308
- async submitDirectAddServerFilesAndPermissionsTransaction(typedData, signature, options) {
4309
- this.assertWallet();
4310
- const chainId = await this.context.publicClient.getChainId();
4311
- const DataPortabilityPermissionsAddress = getContractAddress(
4312
- chainId,
4313
- "DataPortabilityPermissions"
4314
- );
4315
- const DataPortabilityPermissionsAbi = getAbi("DataPortabilityPermissions");
4316
- const serverFilesAndPermissionInput = {
4317
- nonce: typedData.message.nonce,
4318
- granteeId: typedData.message.granteeId,
4319
- grant: typedData.message.grant,
4320
- fileUrls: typedData.message.fileUrls,
4321
- schemaIds: typedData.message.schemaIds,
4322
- serverAddress: typedData.message.serverAddress,
4323
- serverUrl: typedData.message.serverUrl,
4324
- serverPublicKey: typedData.message.serverPublicKey,
4325
- filePermissions: typedData.message.filePermissions
4326
- };
4327
- const formattedSignature = formatSignatureForContract(signature);
4328
- const hash = await this.context.walletClient.writeContract({
4329
- address: DataPortabilityPermissionsAddress,
4330
- abi: DataPortabilityPermissionsAbi,
4331
- functionName: "addServerFilesAndPermissions",
4332
- args: [serverFilesAndPermissionInput, formattedSignature],
4333
- account: this.context.walletClient?.account ?? this.context.userAddress,
4334
- chain: this.context.walletClient?.chain ?? null,
4335
- ...options?.value && { value: options.value },
4336
- ...this.spreadTransactionOptions(options)
4337
- });
4338
- return hash;
4339
- }
4340
- }
4341
- export {
4342
- PermissionsController
4343
- };
4344
- //# sourceMappingURL=permissions.js.map