@opendatalabs/vana-sdk 0.1.0-alpha.fd33fc9 → 2.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 (351) hide show
  1. package/dist/browser.cjs.map +1 -1
  2. package/dist/browser.d.ts +33 -1
  3. package/dist/browser.js.map +1 -1
  4. package/dist/chains/index.cjs.map +1 -1
  5. package/dist/chains/index.d.ts +30 -1
  6. package/dist/chains/index.js.map +1 -1
  7. package/dist/client/__tests__/enhancedResponse.test.d.ts +1 -0
  8. package/dist/client/enhancedResponse.cjs +164 -0
  9. package/dist/client/enhancedResponse.cjs.map +1 -0
  10. package/dist/client/enhancedResponse.d.ts +120 -0
  11. package/dist/client/enhancedResponse.js +138 -0
  12. package/dist/client/enhancedResponse.js.map +1 -0
  13. package/dist/config/chains.cjs.map +1 -1
  14. package/dist/config/chains.d.ts +99 -0
  15. package/dist/config/chains.js.map +1 -1
  16. package/dist/contracts/contractController.cjs.map +1 -1
  17. package/dist/contracts/contractController.d.ts +66 -10
  18. package/dist/contracts/contractController.js.map +1 -1
  19. package/dist/controllers/__tests__/data-consistency-integration.test.d.ts +7 -0
  20. package/dist/controllers/__tests__/operations.processQueue.test.d.ts +1 -0
  21. package/dist/controllers/base.cjs +33 -0
  22. package/dist/controllers/base.cjs.map +1 -1
  23. package/dist/controllers/base.d.ts +10 -0
  24. package/dist/controllers/base.js +33 -0
  25. package/dist/controllers/base.js.map +1 -1
  26. package/dist/controllers/data.cjs +417 -276
  27. package/dist/controllers/data.cjs.map +1 -1
  28. package/dist/controllers/data.d.ts +246 -193
  29. package/dist/controllers/data.js +430 -279
  30. package/dist/controllers/data.js.map +1 -1
  31. package/dist/controllers/operations.cjs +430 -0
  32. package/dist/controllers/operations.cjs.map +1 -0
  33. package/dist/controllers/operations.d.ts +229 -0
  34. package/dist/controllers/operations.js +406 -0
  35. package/dist/controllers/operations.js.map +1 -0
  36. package/dist/controllers/permissions.cjs +690 -209
  37. package/dist/controllers/permissions.cjs.map +1 -1
  38. package/dist/controllers/permissions.d.ts +196 -68
  39. package/dist/controllers/permissions.js +690 -209
  40. package/dist/controllers/permissions.js.map +1 -1
  41. package/dist/controllers/protocol.cjs.map +1 -1
  42. package/dist/controllers/protocol.d.ts +27 -28
  43. package/dist/controllers/protocol.js.map +1 -1
  44. package/dist/controllers/schemas.cjs +104 -25
  45. package/dist/controllers/schemas.cjs.map +1 -1
  46. package/dist/controllers/schemas.d.ts +88 -40
  47. package/dist/controllers/schemas.js +104 -25
  48. package/dist/controllers/schemas.js.map +1 -1
  49. package/dist/controllers/server.cjs +269 -58
  50. package/dist/controllers/server.cjs.map +1 -1
  51. package/dist/controllers/server.d.ts +157 -52
  52. package/dist/controllers/server.js +269 -58
  53. package/dist/controllers/server.js.map +1 -1
  54. package/dist/core/__tests__/health.test.d.ts +1 -0
  55. package/dist/core/__tests__/inMemoryNonceManager.test.d.ts +1 -0
  56. package/dist/core/__tests__/nonceManager.test.d.ts +1 -0
  57. package/dist/core/__tests__/pollingManager.test.d.ts +4 -0
  58. package/dist/core/apiClient.cjs +53 -3
  59. package/dist/core/apiClient.cjs.map +1 -1
  60. package/dist/core/apiClient.d.ts +132 -7
  61. package/dist/core/apiClient.js +53 -3
  62. package/dist/core/apiClient.js.map +1 -1
  63. package/dist/core/generics.cjs +30 -3
  64. package/dist/core/generics.cjs.map +1 -1
  65. package/dist/core/generics.d.ts +95 -6
  66. package/dist/core/generics.js +30 -3
  67. package/dist/core/generics.js.map +1 -1
  68. package/dist/core/health.cjs +289 -0
  69. package/dist/core/health.cjs.map +1 -0
  70. package/dist/core/health.d.ts +143 -0
  71. package/dist/core/health.js +265 -0
  72. package/dist/core/health.js.map +1 -0
  73. package/dist/core/inMemoryNonceManager.cjs +138 -0
  74. package/dist/core/inMemoryNonceManager.cjs.map +1 -0
  75. package/dist/core/inMemoryNonceManager.d.ts +69 -0
  76. package/dist/core/inMemoryNonceManager.js +114 -0
  77. package/dist/core/inMemoryNonceManager.js.map +1 -0
  78. package/dist/core/nonceManager.cjs +304 -0
  79. package/dist/core/nonceManager.cjs.map +1 -0
  80. package/dist/core/nonceManager.d.ts +116 -0
  81. package/dist/core/nonceManager.js +280 -0
  82. package/dist/core/nonceManager.js.map +1 -0
  83. package/dist/core/pollingManager.cjs +292 -0
  84. package/dist/core/pollingManager.cjs.map +1 -0
  85. package/dist/core/pollingManager.d.ts +120 -0
  86. package/dist/core/pollingManager.js +268 -0
  87. package/dist/core/pollingManager.js.map +1 -0
  88. package/dist/core.cjs +55 -1
  89. package/dist/core.cjs.map +1 -1
  90. package/dist/core.d.ts +54 -3
  91. package/dist/core.js +55 -1
  92. package/dist/core.js.map +1 -1
  93. package/dist/crypto/ecies/base.cjs +16 -3
  94. package/dist/crypto/ecies/base.cjs.map +1 -1
  95. package/dist/crypto/ecies/base.js +16 -3
  96. package/dist/crypto/ecies/base.js.map +1 -1
  97. package/dist/errors.cjs +29 -0
  98. package/dist/errors.cjs.map +1 -1
  99. package/dist/errors.d.ts +64 -0
  100. package/dist/errors.js +28 -0
  101. package/dist/errors.js.map +1 -1
  102. package/dist/generated/abi/ComputeInstructionRegistryImplementation.cjs.map +1 -1
  103. package/dist/generated/abi/ComputeInstructionRegistryImplementation.js.map +1 -1
  104. package/dist/generated/abi/DLPPerformanceImplementation.cjs +42 -0
  105. package/dist/generated/abi/DLPPerformanceImplementation.cjs.map +1 -1
  106. package/dist/generated/abi/DLPPerformanceImplementation.d.ts +32 -0
  107. package/dist/generated/abi/DLPPerformanceImplementation.js +42 -0
  108. package/dist/generated/abi/DLPPerformanceImplementation.js.map +1 -1
  109. package/dist/generated/abi/DLPRegistryImplementation.cjs +5 -5
  110. package/dist/generated/abi/DLPRegistryImplementation.cjs.map +1 -1
  111. package/dist/generated/abi/DLPRegistryImplementation.d.ts +4 -4
  112. package/dist/generated/abi/DLPRegistryImplementation.js +5 -5
  113. package/dist/generated/abi/DLPRegistryImplementation.js.map +1 -1
  114. package/dist/generated/abi/DLPRewardDeployerImplementation.cjs +166 -2
  115. package/dist/generated/abi/DLPRewardDeployerImplementation.cjs.map +1 -1
  116. package/dist/generated/abi/DLPRewardDeployerImplementation.d.ts +129 -2
  117. package/dist/generated/abi/DLPRewardDeployerImplementation.js +166 -2
  118. package/dist/generated/abi/DLPRewardDeployerImplementation.js.map +1 -1
  119. package/dist/generated/abi/DataPortabilityGranteesImplementation.cjs +167 -19
  120. package/dist/generated/abi/DataPortabilityGranteesImplementation.cjs.map +1 -1
  121. package/dist/generated/abi/DataPortabilityGranteesImplementation.d.ts +127 -14
  122. package/dist/generated/abi/DataPortabilityGranteesImplementation.js +167 -19
  123. package/dist/generated/abi/DataPortabilityGranteesImplementation.js.map +1 -1
  124. package/dist/generated/abi/DataPortabilityPermissionsImplementation.cjs +0 -19
  125. package/dist/generated/abi/DataPortabilityPermissionsImplementation.cjs.map +1 -1
  126. package/dist/generated/abi/DataPortabilityPermissionsImplementation.d.ts +0 -14
  127. package/dist/generated/abi/DataPortabilityPermissionsImplementation.js +0 -19
  128. package/dist/generated/abi/DataPortabilityPermissionsImplementation.js.map +1 -1
  129. package/dist/generated/abi/DataPortabilityServersImplementation.cjs +0 -19
  130. package/dist/generated/abi/DataPortabilityServersImplementation.cjs.map +1 -1
  131. package/dist/generated/abi/DataPortabilityServersImplementation.d.ts +0 -14
  132. package/dist/generated/abi/DataPortabilityServersImplementation.js +0 -19
  133. package/dist/generated/abi/DataPortabilityServersImplementation.js.map +1 -1
  134. package/dist/generated/abi/DataRegistryImplementation.cjs +0 -13
  135. package/dist/generated/abi/DataRegistryImplementation.cjs.map +1 -1
  136. package/dist/generated/abi/DataRegistryImplementation.d.ts +0 -10
  137. package/dist/generated/abi/DataRegistryImplementation.js +0 -13
  138. package/dist/generated/abi/DataRegistryImplementation.js.map +1 -1
  139. package/dist/generated/abi/SwapHelperImplementation.cjs +0 -43
  140. package/dist/generated/abi/SwapHelperImplementation.cjs.map +1 -1
  141. package/dist/generated/abi/SwapHelperImplementation.d.ts +0 -35
  142. package/dist/generated/abi/SwapHelperImplementation.js +0 -43
  143. package/dist/generated/abi/SwapHelperImplementation.js.map +1 -1
  144. package/dist/generated/abi/VanaEpochImplementation.cjs +195 -0
  145. package/dist/generated/abi/VanaEpochImplementation.cjs.map +1 -1
  146. package/dist/generated/abi/VanaEpochImplementation.d.ts +151 -0
  147. package/dist/generated/abi/VanaEpochImplementation.js +195 -0
  148. package/dist/generated/abi/VanaEpochImplementation.js.map +1 -1
  149. package/dist/generated/abi/VanaPoolEntityImplementation.cjs +22 -65
  150. package/dist/generated/abi/VanaPoolEntityImplementation.cjs.map +1 -1
  151. package/dist/generated/abi/VanaPoolEntityImplementation.d.ts +17 -51
  152. package/dist/generated/abi/VanaPoolEntityImplementation.js +22 -65
  153. package/dist/generated/abi/VanaPoolEntityImplementation.js.map +1 -1
  154. package/dist/generated/abi/VanaPoolStakingImplementation.cjs +113 -1
  155. package/dist/generated/abi/VanaPoolStakingImplementation.cjs.map +1 -1
  156. package/dist/generated/abi/VanaPoolStakingImplementation.d.ts +85 -1
  157. package/dist/generated/abi/VanaPoolStakingImplementation.js +113 -1
  158. package/dist/generated/abi/VanaPoolStakingImplementation.js.map +1 -1
  159. package/dist/generated/abi/index.d.ts +546 -146
  160. package/dist/generated/event-types.cjs.map +1 -1
  161. package/dist/generated/event-types.d.ts +14 -8
  162. package/dist/generated/eventRegistry.cjs +42 -18
  163. package/dist/generated/eventRegistry.cjs.map +1 -1
  164. package/dist/generated/eventRegistry.js +42 -18
  165. package/dist/generated/eventRegistry.js.map +1 -1
  166. package/dist/generated/server/server-exports.cjs +22 -0
  167. package/dist/generated/server/server-exports.cjs.map +1 -1
  168. package/dist/generated/server/server-exports.d.ts +27 -10
  169. package/dist/generated/server/server-exports.js +17 -0
  170. package/dist/generated/server/server-exports.js.map +1 -1
  171. package/dist/generated/server/server.cjs.map +1 -1
  172. package/dist/generated/server/server.d.ts +771 -402
  173. package/dist/generated/subgraph.cjs +797 -32
  174. package/dist/generated/subgraph.cjs.map +1 -1
  175. package/dist/generated/subgraph.d.ts +135 -0
  176. package/dist/generated/subgraph.js +792 -32
  177. package/dist/generated/subgraph.js.map +1 -1
  178. package/dist/index.browser.d.ts +2 -0
  179. package/dist/index.browser.js +10 -0
  180. package/dist/index.browser.js.map +1 -1
  181. package/dist/index.cjs.map +1 -1
  182. package/dist/index.js.map +1 -1
  183. package/dist/index.node.cjs +26 -0
  184. package/dist/index.node.cjs.map +1 -1
  185. package/dist/index.node.d.ts +49 -5
  186. package/dist/index.node.js +25 -1
  187. package/dist/index.node.js.map +1 -1
  188. package/dist/lib/__tests__/redisAtomicStore.test.d.ts +1 -0
  189. package/dist/lib/redisAtomicStore.cjs +201 -0
  190. package/dist/lib/redisAtomicStore.cjs.map +1 -0
  191. package/dist/lib/redisAtomicStore.d.ts +120 -0
  192. package/dist/lib/redisAtomicStore.js +177 -0
  193. package/dist/lib/redisAtomicStore.js.map +1 -0
  194. package/dist/node.cjs.map +1 -1
  195. package/dist/node.d.ts +39 -1
  196. package/dist/node.js.map +1 -1
  197. package/dist/platform/browser.cjs +160 -2
  198. package/dist/platform/browser.cjs.map +1 -1
  199. package/dist/platform/browser.d.ts +232 -12
  200. package/dist/platform/browser.js +160 -2
  201. package/dist/platform/browser.js.map +1 -1
  202. package/dist/platform/interface.cjs.map +1 -1
  203. package/dist/platform/interface.d.ts +283 -90
  204. package/dist/platform/node.cjs +163 -2
  205. package/dist/platform/node.cjs.map +1 -1
  206. package/dist/platform/node.d.ts +69 -6
  207. package/dist/platform/node.js +163 -2
  208. package/dist/platform/node.js.map +1 -1
  209. package/dist/server/relayerHandler.cjs +315 -81
  210. package/dist/server/relayerHandler.cjs.map +1 -1
  211. package/dist/server/relayerHandler.d.ts +35 -2
  212. package/dist/server/relayerHandler.js +315 -81
  213. package/dist/server/relayerHandler.js.map +1 -1
  214. package/dist/storage/index.cjs +3 -0
  215. package/dist/storage/index.cjs.map +1 -1
  216. package/dist/storage/index.d.ts +1 -0
  217. package/dist/storage/index.js +2 -0
  218. package/dist/storage/index.js.map +1 -1
  219. package/dist/storage/manager.cjs +108 -25
  220. package/dist/storage/manager.cjs.map +1 -1
  221. package/dist/storage/manager.d.ts +119 -25
  222. package/dist/storage/manager.js +108 -25
  223. package/dist/storage/manager.js.map +1 -1
  224. package/dist/storage/providers/callback-storage.cjs +86 -15
  225. package/dist/storage/providers/callback-storage.cjs.map +1 -1
  226. package/dist/storage/providers/callback-storage.d.ts +109 -20
  227. package/dist/storage/providers/callback-storage.js +86 -15
  228. package/dist/storage/providers/callback-storage.js.map +1 -1
  229. package/dist/storage/providers/dropbox.cjs +237 -0
  230. package/dist/storage/providers/dropbox.cjs.map +1 -0
  231. package/dist/storage/providers/dropbox.d.ts +39 -0
  232. package/dist/storage/providers/dropbox.js +215 -0
  233. package/dist/storage/providers/dropbox.js.map +1 -0
  234. package/dist/storage/providers/dropbox.test.d.ts +1 -0
  235. package/dist/storage/providers/pinata.cjs.map +1 -1
  236. package/dist/storage/providers/pinata.d.ts +12 -14
  237. package/dist/storage/providers/pinata.js.map +1 -1
  238. package/dist/tests/data-upload-owner-validation.test.d.ts +1 -0
  239. package/dist/tests/permissions-transaction-options.test.d.ts +1 -0
  240. package/dist/types/atomicStore.cjs +31 -0
  241. package/dist/types/atomicStore.cjs.map +1 -0
  242. package/dist/types/atomicStore.d.ts +236 -0
  243. package/dist/types/atomicStore.js +7 -0
  244. package/dist/types/atomicStore.js.map +1 -0
  245. package/dist/types/blockchain.cjs.map +1 -1
  246. package/dist/types/blockchain.d.ts +39 -11
  247. package/dist/types/chains.cjs.map +1 -1
  248. package/dist/types/chains.d.ts +74 -7
  249. package/dist/types/chains.js.map +1 -1
  250. package/dist/types/config.cjs.map +1 -1
  251. package/dist/types/config.d.ts +38 -4
  252. package/dist/types/config.js.map +1 -1
  253. package/dist/types/contracts.cjs.map +1 -1
  254. package/dist/types/contracts.d.ts +71 -7
  255. package/dist/types/controller-context.cjs.map +1 -1
  256. package/dist/types/controller-context.d.ts +4 -1
  257. package/dist/types/data.cjs.map +1 -1
  258. package/dist/types/data.d.ts +11 -10
  259. package/dist/types/generics.cjs.map +1 -1
  260. package/dist/types/generics.d.ts +81 -10
  261. package/dist/types/index.cjs.map +1 -1
  262. package/dist/types/index.d.ts +31 -3
  263. package/dist/types/index.js.map +1 -1
  264. package/dist/types/operationStore.cjs +17 -0
  265. package/dist/types/operationStore.cjs.map +1 -0
  266. package/dist/types/operationStore.d.ts +171 -0
  267. package/dist/types/operationStore.js +1 -0
  268. package/dist/types/operationStore.js.map +1 -0
  269. package/dist/types/operations.cjs +3 -15
  270. package/dist/types/operations.cjs.map +1 -1
  271. package/dist/types/operations.d.ts +131 -39
  272. package/dist/types/operations.js +2 -13
  273. package/dist/types/operations.js.map +1 -1
  274. package/dist/types/options.cjs +17 -0
  275. package/dist/types/options.cjs.map +1 -0
  276. package/dist/types/options.d.ts +308 -0
  277. package/dist/types/options.js +1 -0
  278. package/dist/types/options.js.map +1 -0
  279. package/dist/types/permissions.cjs.map +1 -1
  280. package/dist/types/permissions.d.ts +19 -20
  281. package/dist/types/personal.cjs.map +1 -1
  282. package/dist/types/personal.d.ts +150 -14
  283. package/dist/types/relayer.cjs.map +1 -1
  284. package/dist/types/relayer.d.ts +145 -24
  285. package/dist/types/storage.cjs.map +1 -1
  286. package/dist/types/storage.d.ts +9 -21
  287. package/dist/types/storage.js.map +1 -1
  288. package/dist/types/utils.cjs.map +1 -1
  289. package/dist/types/utils.d.ts +0 -45
  290. package/dist/utils/__tests__/chainQuery.test.d.ts +1 -0
  291. package/dist/utils/__tests__/subgraphConsistency.test.d.ts +4 -0
  292. package/dist/utils/__tests__/subgraphPagination.test.d.ts +4 -0
  293. package/dist/utils/chainQuery.cjs +107 -0
  294. package/dist/utils/chainQuery.cjs.map +1 -0
  295. package/dist/utils/chainQuery.d.ts +31 -0
  296. package/dist/utils/chainQuery.js +82 -0
  297. package/dist/utils/chainQuery.js.map +1 -0
  298. package/dist/utils/grantFiles.cjs +4 -1
  299. package/dist/utils/grantFiles.cjs.map +1 -1
  300. package/dist/utils/grantFiles.d.ts +10 -20
  301. package/dist/utils/grantFiles.js +4 -1
  302. package/dist/utils/grantFiles.js.map +1 -1
  303. package/dist/utils/grantValidation.cjs.map +1 -1
  304. package/dist/utils/grantValidation.d.ts +95 -16
  305. package/dist/utils/grantValidation.js.map +1 -1
  306. package/dist/utils/grants.cjs.map +1 -1
  307. package/dist/utils/grants.d.ts +93 -12
  308. package/dist/utils/grants.js.map +1 -1
  309. package/dist/utils/ipfs.cjs +2 -4
  310. package/dist/utils/ipfs.cjs.map +1 -1
  311. package/dist/utils/ipfs.d.ts +1 -1
  312. package/dist/utils/ipfs.js +2 -4
  313. package/dist/utils/ipfs.js.map +1 -1
  314. package/dist/utils/lazy-import.cjs.map +1 -1
  315. package/dist/utils/lazy-import.d.ts +32 -7
  316. package/dist/utils/lazy-import.js.map +1 -1
  317. package/dist/utils/signatureCache.cjs +8 -2
  318. package/dist/utils/signatureCache.cjs.map +1 -1
  319. package/dist/utils/signatureCache.d.ts +49 -8
  320. package/dist/utils/signatureCache.js +8 -2
  321. package/dist/utils/signatureCache.js.map +1 -1
  322. package/dist/utils/subgraphConsistency.cjs +184 -0
  323. package/dist/utils/subgraphConsistency.cjs.map +1 -0
  324. package/dist/utils/subgraphConsistency.d.ts +65 -0
  325. package/dist/utils/subgraphConsistency.js +155 -0
  326. package/dist/utils/subgraphConsistency.js.map +1 -0
  327. package/dist/utils/subgraphMetaCache.cjs +101 -0
  328. package/dist/utils/subgraphMetaCache.cjs.map +1 -0
  329. package/dist/utils/subgraphMetaCache.d.ts +56 -0
  330. package/dist/utils/subgraphMetaCache.js +76 -0
  331. package/dist/utils/subgraphMetaCache.js.map +1 -0
  332. package/dist/utils/subgraphPagination.cjs +104 -0
  333. package/dist/utils/subgraphPagination.cjs.map +1 -0
  334. package/dist/utils/subgraphPagination.d.ts +78 -0
  335. package/dist/utils/subgraphPagination.js +78 -0
  336. package/dist/utils/subgraphPagination.js.map +1 -0
  337. package/dist/utils/transactionHelpers.cjs.map +1 -1
  338. package/dist/utils/transactionHelpers.d.ts +12 -12
  339. package/dist/utils/transactionHelpers.js.map +1 -1
  340. package/dist/utils/typedDataConverter.cjs.map +1 -1
  341. package/dist/utils/typedDataConverter.d.ts +39 -3
  342. package/dist/utils/typedDataConverter.js.map +1 -1
  343. package/dist/utils/urlResolver.cjs +7 -0
  344. package/dist/utils/urlResolver.cjs.map +1 -1
  345. package/dist/utils/urlResolver.d.ts +22 -4
  346. package/dist/utils/urlResolver.js +7 -0
  347. package/dist/utils/urlResolver.js.map +1 -1
  348. package/dist/utils/wallet.cjs.map +1 -1
  349. package/dist/utils/wallet.d.ts +78 -16
  350. package/dist/utils/wallet.js.map +1 -1
  351. package/package.json +3 -1
@@ -1,5 +1,6 @@
1
1
  import { getAddress } from "viem";
2
2
  import { gasAwareMulticall } from "../utils/multicall";
3
+ import { PollingManager } from "../core/pollingManager";
3
4
  import {
4
5
  RelayerError,
5
6
  UserRejectedRequestError,
@@ -57,10 +58,14 @@ class PermissionsController extends BaseController {
57
58
  * await vana.permissions.revoke({ permissionId: result.permissionId });
58
59
  * ```
59
60
  */
60
- async grant(params) {
61
+ async grant(params, options) {
61
62
  this.assertWallet();
62
63
  const { typedData, signature } = await this.createAndSign(params);
63
- const result = await this.submitSignedGrantWithEvents(typedData, signature);
64
+ const result = await this.submitSignedGrantWithEvents(
65
+ typedData,
66
+ signature,
67
+ options
68
+ );
64
69
  return result;
65
70
  }
66
71
  /**
@@ -88,10 +93,10 @@ class PermissionsController extends BaseController {
88
93
  * console.log(`Permission ID: ${eventData.permissionId}`);
89
94
  * ```
90
95
  */
91
- async submitPermissionGrant(params) {
96
+ async submitPermissionGrant(params, options) {
92
97
  this.assertWallet();
93
98
  const { typedData, signature } = await this.createAndSign(params);
94
- return await this.submitSignedGrant(typedData, signature);
99
+ return await this.submitSignedGrant(typedData, signature, options);
95
100
  }
96
101
  /**
97
102
  * Prepares a permission grant with preview before signing.
@@ -118,7 +123,7 @@ class PermissionsController extends BaseController {
118
123
  * const transactionHash = await confirm();
119
124
  * ```
120
125
  */
121
- async prepareGrant(params) {
126
+ async prepareGrant(params, options) {
122
127
  this.assertWallet();
123
128
  try {
124
129
  const grantFile = createGrantFile(params);
@@ -126,7 +131,11 @@ class PermissionsController extends BaseController {
126
131
  return {
127
132
  preview: grantFile,
128
133
  confirm: async () => {
129
- return await this.confirmGrantInternalWithEvents(params, grantFile);
134
+ return await this.confirmGrantInternalWithEvents(
135
+ params,
136
+ grantFile,
137
+ options
138
+ );
130
139
  }
131
140
  };
132
141
  } catch (error) {
@@ -158,7 +167,7 @@ class PermissionsController extends BaseController {
158
167
  * @throws {NetworkError} When IPFS upload fails
159
168
  * @throws {SignatureError} When user rejects the signature
160
169
  */
161
- async confirmGrantInternal(params, grantFile) {
170
+ async confirmGrantInternal(params, grantFile, options) {
162
171
  try {
163
172
  let { grantUrl } = params;
164
173
  console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
@@ -183,7 +192,7 @@ class PermissionsController extends BaseController {
183
192
  if (response.type === "error") {
184
193
  throw new Error(response.error);
185
194
  }
186
- if (response.type === "direct" && typeof response.result === "object" && "url" in response.result) {
195
+ if (response.type === "direct" && typeof response.result === "object" && response.result !== null && "url" in response.result) {
187
196
  grantUrl = response.result.url;
188
197
  } else {
189
198
  throw new Error("Invalid response from relayer for grant storage");
@@ -219,7 +228,7 @@ class PermissionsController extends BaseController {
219
228
  nonce
220
229
  });
221
230
  const signature = await this.signTypedData(typedData);
222
- return await this.submitSignedGrant(typedData, signature);
231
+ return await this.submitSignedGrant(typedData, signature, options);
223
232
  } catch (error) {
224
233
  if (error instanceof Error) {
225
234
  if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
@@ -291,7 +300,7 @@ class PermissionsController extends BaseController {
291
300
  if (response.type === "error") {
292
301
  throw new Error(response.error);
293
302
  }
294
- if (response.type === "direct" && typeof response.result === "object" && "url" in response.result) {
303
+ if (response.type === "direct" && typeof response.result === "object" && response.result !== null && "url" in response.result) {
295
304
  grantUrl = response.result.url;
296
305
  } else {
297
306
  throw new Error("Invalid response from relayer for grant storage");
@@ -364,7 +373,7 @@ class PermissionsController extends BaseController {
364
373
  * );
365
374
  * ```
366
375
  */
367
- async submitSignedGrant(typedData, signature) {
376
+ async submitSignedGrant(typedData, signature, options) {
368
377
  try {
369
378
  console.debug(
370
379
  "\u{1F50D} Debug - submitSignedGrant called with typed data:",
@@ -382,26 +391,41 @@ class PermissionsController extends BaseController {
382
391
  signature,
383
392
  expectedUserAddress: this.context.userAddress
384
393
  });
385
- let hash;
386
- if (response.type === "signed") {
387
- hash = response.hash;
388
- } else if (response.type === "error") {
394
+ if (response.type === "error") {
389
395
  throw new Error(`Relayer error: ${response.error}`);
396
+ }
397
+ let finalHash;
398
+ if (response.type === "submitted") {
399
+ finalHash = response.hash;
400
+ } else if (response.type === "pending") {
401
+ const pollResult = await this.pollRelayerForConfirmation(
402
+ response.operationId,
403
+ options
404
+ );
405
+ finalHash = pollResult.hash;
406
+ } else if (response.type === "confirmed") {
407
+ finalHash = response.hash;
408
+ } else if (response.type === "signed") {
409
+ finalHash = response.hash;
390
410
  } else {
391
411
  throw new Error(
392
- "Invalid response from relayer: expected signed transaction"
412
+ "Invalid response from relayer: unexpected response type"
393
413
  );
394
414
  }
395
415
  const account = this.context.walletClient?.account ?? this.context.userAddress;
396
416
  const { tx } = await import("../utils/transactionHelpers");
397
417
  return tx({
398
- hash,
418
+ hash: finalHash,
399
419
  from: typeof account === "string" ? account : account.address,
400
420
  contract: "DataPortabilityPermissions",
401
421
  fn: "addPermission"
402
422
  });
403
423
  } else {
404
- return await this.submitDirectTransaction(typedData, signature);
424
+ return await this.submitDirectTransaction(
425
+ typedData,
426
+ signature,
427
+ options
428
+ );
405
429
  }
406
430
  } catch (error) {
407
431
  if (error instanceof RelayerError || error instanceof NetworkError || error instanceof UserRejectedRequestError || error instanceof SignatureError || error instanceof NonceError) {
@@ -434,7 +458,7 @@ class PermissionsController extends BaseController {
434
458
  * const result = await txHandle.waitForEvents();
435
459
  * ```
436
460
  */
437
- async submitSignedTrustServer(typedData, signature) {
461
+ async submitSignedTrustServer(typedData, signature, options) {
438
462
  try {
439
463
  const trustServerInput = {
440
464
  nonce: BigInt(typedData.message.nonce),
@@ -442,7 +466,8 @@ class PermissionsController extends BaseController {
442
466
  };
443
467
  const hash = await this.submitTrustServerTransaction(
444
468
  trustServerInput,
445
- signature
469
+ signature,
470
+ options
446
471
  );
447
472
  const account = this.context.userAddress;
448
473
  const { tx } = await import("../utils/transactionHelpers");
@@ -497,7 +522,7 @@ class PermissionsController extends BaseController {
497
522
  * const result = await txHandle.waitForEvents();
498
523
  * ```
499
524
  */
500
- async submitSignedAddAndTrustServer(typedData, signature) {
525
+ async submitSignedAddAndTrustServer(typedData, signature, options) {
501
526
  try {
502
527
  const addAndTrustServerInput = {
503
528
  nonce: BigInt(typedData.message.nonce),
@@ -507,7 +532,8 @@ class PermissionsController extends BaseController {
507
532
  };
508
533
  const hash = await this.submitAddAndTrustServerTransaction(
509
534
  addAndTrustServerInput,
510
- signature
535
+ signature,
536
+ options
511
537
  );
512
538
  const account = this.context.walletClient?.account ?? this.context.userAddress;
513
539
  const { tx } = await import("../utils/transactionHelpers");
@@ -535,8 +561,12 @@ class PermissionsController extends BaseController {
535
561
  * @param signature - The user's signature authorizing the transaction
536
562
  * @returns Promise resolving to PermissionGrantResult with parsed events
537
563
  */
538
- async submitSignedGrantWithEvents(typedData, signature) {
539
- const txResult = await this.submitSignedGrant(typedData, signature);
564
+ async submitSignedGrantWithEvents(typedData, signature, options) {
565
+ const txResult = await this.submitSignedGrant(
566
+ typedData,
567
+ signature,
568
+ options
569
+ );
540
570
  if (!this.context.waitForTransactionEvents) {
541
571
  throw new BlockchainError("waitForTransactionEvents not configured");
542
572
  }
@@ -568,8 +598,12 @@ class PermissionsController extends BaseController {
568
598
  * @param grantFile - The pre-created grant file object
569
599
  * @returns Promise resolving to PermissionGrantResult with parsed events
570
600
  */
571
- async confirmGrantInternalWithEvents(params, grantFile) {
572
- const txResult = await this.confirmGrantInternal(params, grantFile);
601
+ async confirmGrantInternalWithEvents(params, grantFile, options) {
602
+ const txResult = await this.confirmGrantInternal(
603
+ params,
604
+ grantFile,
605
+ options
606
+ );
573
607
  if (!this.context.waitForTransactionEvents) {
574
608
  throw new BlockchainError("waitForTransactionEvents not configured");
575
609
  }
@@ -593,6 +627,27 @@ class PermissionsController extends BaseController {
593
627
  fileIds: event.fileIds
594
628
  };
595
629
  }
630
+ /**
631
+ * Polls the relayer for confirmation of a pending operation.
632
+ *
633
+ * @param operationId - The operation ID to poll
634
+ * @param options - Polling configuration including status updates and cancellation
635
+ * @returns Promise resolving to the confirmed hash and receipt
636
+ * @throws {TransactionPendingError} When the operation times out
637
+ * @throws {Error} When the operation fails or is cancelled
638
+ * @internal
639
+ */
640
+ async pollRelayerForConfirmation(operationId, options) {
641
+ if (!this.context.relayer) {
642
+ throw new Error("Relayer not configured for polling");
643
+ }
644
+ const pollingManager = new PollingManager(this.context.relayer);
645
+ return await pollingManager.startPolling(operationId, {
646
+ signal: options?.signal,
647
+ onStatusUpdate: options?.onStatusUpdate,
648
+ ...options?.pollingOptions
649
+ });
650
+ }
596
651
  /**
597
652
  * Submits an already-signed permission revoke transaction to the blockchain.
598
653
  *
@@ -614,7 +669,7 @@ class PermissionsController extends BaseController {
614
669
  * const result = await txHandle.waitForEvents();
615
670
  * ```
616
671
  */
617
- async submitSignedRevoke(typedData, signature) {
672
+ async submitSignedRevoke(typedData, signature, options) {
618
673
  try {
619
674
  let hash;
620
675
  if (this.context.relayer) {
@@ -625,19 +680,31 @@ class PermissionsController extends BaseController {
625
680
  signature,
626
681
  expectedUserAddress: this.context.userAddress
627
682
  });
628
- if (response.type === "signed") {
629
- hash = response.hash;
630
- } else if (response.type === "error") {
683
+ if (response.type === "error") {
631
684
  throw new Error(`Relayer error: ${response.error}`);
685
+ }
686
+ if (response.type === "submitted") {
687
+ hash = response.hash;
688
+ } else if (response.type === "pending") {
689
+ const pollResult = await this.pollRelayerForConfirmation(
690
+ response.operationId,
691
+ options
692
+ );
693
+ hash = pollResult.hash;
694
+ } else if (response.type === "confirmed") {
695
+ hash = response.hash;
696
+ } else if (response.type === "signed") {
697
+ hash = response.hash;
632
698
  } else {
633
699
  throw new Error(
634
- "Invalid response from relayer: expected signed transaction"
700
+ "Invalid response from relayer: unexpected response type"
635
701
  );
636
702
  }
637
703
  } else {
638
704
  hash = await this.submitDirectRevokeTransaction(
639
705
  typedData,
640
- signature
706
+ signature,
707
+ options
641
708
  );
642
709
  }
643
710
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -679,7 +746,7 @@ class PermissionsController extends BaseController {
679
746
  * const result = await txHandle.waitForEvents();
680
747
  * ```
681
748
  */
682
- async submitSignedUntrustServer(typedData, signature) {
749
+ async submitSignedUntrustServer(typedData, signature, options) {
683
750
  try {
684
751
  let hash;
685
752
  if (this.context.relayer) {
@@ -690,7 +757,9 @@ class PermissionsController extends BaseController {
690
757
  signature,
691
758
  expectedUserAddress: this.context.userAddress
692
759
  });
693
- if (response.type === "signed") {
760
+ if (response.type === "submitted") {
761
+ hash = response.hash;
762
+ } else if (response.type === "signed") {
694
763
  hash = response.hash;
695
764
  } else if (response.type === "error") {
696
765
  throw new Error(`Relayer error: ${response.error}`);
@@ -702,7 +771,8 @@ class PermissionsController extends BaseController {
702
771
  } else {
703
772
  hash = await this.submitSignedUntrustTransaction(
704
773
  typedData,
705
- signature
774
+ signature,
775
+ options
706
776
  );
707
777
  }
708
778
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -735,7 +805,7 @@ class PermissionsController extends BaseController {
735
805
  * @returns Promise resolving to the transaction hash
736
806
  * @throws {BlockchainError} When contract submission fails
737
807
  */
738
- async submitDirectTransaction(typedData, signature) {
808
+ async submitDirectTransaction(typedData, signature, options) {
739
809
  this.assertWallet();
740
810
  const chainId = await this.context.publicClient.getChainId();
741
811
  const DataPortabilityPermissionsAddress = getContractAddress(
@@ -767,7 +837,8 @@ class PermissionsController extends BaseController {
767
837
  functionName: "addPermission",
768
838
  args: [permissionInput, formattedSignature],
769
839
  account,
770
- chain: this.context.walletClient?.chain ?? null
840
+ chain: this.context.walletClient?.chain ?? null,
841
+ ...this.spreadTransactionOptions(options)
771
842
  });
772
843
  const { tx } = await import("../utils/transactionHelpers");
773
844
  return tx({
@@ -831,6 +902,7 @@ class PermissionsController extends BaseController {
831
902
  * Use this when you want to handle transaction confirmation and event parsing separately.
832
903
  *
833
904
  * @param params - Parameters for revoking the permission
905
+ * @param options - Optional transaction options for gas parameters and timeout
834
906
  * @returns Promise resolving to the transaction hash when successfully submitted
835
907
  * @throws {BlockchainError} When revocation transaction fails
836
908
  * @throws {UserRejectedRequestError} When user rejects the transaction
@@ -843,7 +915,7 @@ class PermissionsController extends BaseController {
843
915
  * console.log(`Revocation submitted: ${txHash}`);
844
916
  * ```
845
917
  */
846
- async submitPermissionRevoke(params) {
918
+ async submitPermissionRevoke(params, options) {
847
919
  this.assertWallet();
848
920
  try {
849
921
  if (!this.context.walletClient?.chain?.id) {
@@ -864,7 +936,18 @@ class PermissionsController extends BaseController {
864
936
  functionName: "revokePermission",
865
937
  args: [params.permissionId],
866
938
  account,
867
- chain: this.context.walletClient?.chain ?? null
939
+ chain: this.context.walletClient?.chain ?? null,
940
+ ...options?.gas && { gas: options.gas },
941
+ ...options?.nonce && { nonce: options.nonce },
942
+ // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
943
+ ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
944
+ ...options.maxFeePerGas && {
945
+ maxFeePerGas: options.maxFeePerGas
946
+ },
947
+ ...options.maxPriorityFeePerGas && {
948
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
949
+ }
950
+ } : options?.gasPrice && { gasPrice: options.gasPrice }
868
951
  });
869
952
  const { tx } = await import("../utils/transactionHelpers");
870
953
  return tx({
@@ -911,7 +994,7 @@ class PermissionsController extends BaseController {
911
994
  * console.log(`Permission ${result.permissionId} revoked`);
912
995
  * ```
913
996
  */
914
- async submitRevokeWithSignature(params) {
997
+ async submitRevokeWithSignature(params, options) {
915
998
  this.assertWallet();
916
999
  try {
917
1000
  if (!this.context.walletClient?.chain?.id) {
@@ -943,7 +1026,9 @@ class PermissionsController extends BaseController {
943
1026
  signature,
944
1027
  expectedUserAddress: this.context.userAddress
945
1028
  });
946
- if (response.type === "signed") {
1029
+ if (response.type === "submitted") {
1030
+ hash = response.hash;
1031
+ } else if (response.type === "signed") {
947
1032
  hash = response.hash;
948
1033
  } else if (response.type === "error") {
949
1034
  throw new Error(`Relayer error: ${response.error}`);
@@ -955,7 +1040,8 @@ class PermissionsController extends BaseController {
955
1040
  } else {
956
1041
  hash = await this.submitDirectRevokeTransaction(
957
1042
  typedData,
958
- signature
1043
+ signature,
1044
+ options
959
1045
  );
960
1046
  }
961
1047
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -1281,7 +1367,9 @@ class PermissionsController extends BaseController {
1281
1367
  * ```
1282
1368
  */
1283
1369
  async getUserPermissionGrantsOnChain(options = {}) {
1284
- const { limit = 50, subgraphUrl } = options;
1370
+ const { limit = 50, fetchAll = false, subgraphUrl } = options;
1371
+ const pageSize = fetchAll ? 100 : limit;
1372
+ const maxResults = fetchAll ? 1e4 : limit;
1285
1373
  try {
1286
1374
  const userAddress = this.context.userAddress;
1287
1375
  const graphqlEndpoint = subgraphUrl ?? this.context.subgraphUrl;
@@ -1291,10 +1379,10 @@ class PermissionsController extends BaseController {
1291
1379
  );
1292
1380
  }
1293
1381
  const query = `
1294
- query GetUserPermissions($userId: ID!) {
1382
+ query GetUserPermissions($userId: ID!, $first: Int!, $skip: Int!) {
1295
1383
  user(id: $userId) {
1296
1384
  id
1297
- permissions {
1385
+ permissions(first: $first, skip: $skip, orderBy: addedAtBlock, orderDirection: desc) {
1298
1386
  id
1299
1387
  grant
1300
1388
  nonce
@@ -1312,34 +1400,82 @@ class PermissionsController extends BaseController {
1312
1400
  }
1313
1401
  }
1314
1402
  `;
1315
- const response = await fetch(graphqlEndpoint, {
1316
- method: "POST",
1317
- headers: {
1318
- "Content-Type": "application/json"
1319
- },
1320
- body: JSON.stringify({
1321
- query,
1322
- variables: {
1323
- userId: userAddress.toLowerCase()
1403
+ const allPermissions = [];
1404
+ let currentOffset = 0;
1405
+ if (!fetchAll) {
1406
+ const response = await fetch(graphqlEndpoint, {
1407
+ method: "POST",
1408
+ headers: {
1409
+ "Content-Type": "application/json"
1410
+ },
1411
+ body: JSON.stringify({
1412
+ query,
1413
+ variables: {
1414
+ userId: userAddress.toLowerCase(),
1415
+ first: limit,
1416
+ skip: 0
1417
+ }
1418
+ })
1419
+ });
1420
+ if (!response.ok) {
1421
+ throw new BlockchainError(
1422
+ `Subgraph request failed: ${response.status} ${response.statusText}`
1423
+ );
1424
+ }
1425
+ const result = await response.json();
1426
+ if (result.errors) {
1427
+ throw new BlockchainError(
1428
+ `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
1429
+ );
1430
+ }
1431
+ const userData = result.data?.user;
1432
+ if (!userData?.permissions?.length) {
1433
+ return [];
1434
+ }
1435
+ allPermissions.push(...userData.permissions);
1436
+ } else {
1437
+ while (allPermissions.length < maxResults) {
1438
+ const currentLimit = Math.min(
1439
+ pageSize,
1440
+ maxResults - allPermissions.length
1441
+ );
1442
+ const response = await fetch(graphqlEndpoint, {
1443
+ method: "POST",
1444
+ headers: {
1445
+ "Content-Type": "application/json"
1446
+ },
1447
+ body: JSON.stringify({
1448
+ query,
1449
+ variables: {
1450
+ userId: userAddress.toLowerCase(),
1451
+ first: currentLimit,
1452
+ skip: currentOffset
1453
+ }
1454
+ })
1455
+ });
1456
+ if (!response.ok) {
1457
+ throw new BlockchainError(
1458
+ `Subgraph request failed: ${response.status} ${response.statusText}`
1459
+ );
1324
1460
  }
1325
- })
1326
- });
1327
- if (!response.ok) {
1328
- throw new BlockchainError(
1329
- `Subgraph request failed: ${response.status} ${response.statusText}`
1330
- );
1331
- }
1332
- const result = await response.json();
1333
- if (result.errors) {
1334
- throw new BlockchainError(
1335
- `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
1336
- );
1337
- }
1338
- const userData = result.data?.user;
1339
- if (!userData?.permissions?.length) {
1340
- return [];
1461
+ const result = await response.json();
1462
+ if (result.errors) {
1463
+ throw new BlockchainError(
1464
+ `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
1465
+ );
1466
+ }
1467
+ const userData = result.data?.user;
1468
+ if (!userData?.permissions?.length) {
1469
+ break;
1470
+ }
1471
+ allPermissions.push(...userData.permissions);
1472
+ if (userData.permissions.length < currentLimit) {
1473
+ break;
1474
+ }
1475
+ currentOffset += userData.permissions.length;
1476
+ }
1341
1477
  }
1342
- const onChainGrants = userData.permissions.slice(0, limit).map(
1478
+ const onChainGrants = allPermissions.map(
1343
1479
  (permission) => ({
1344
1480
  id: BigInt(permission.id),
1345
1481
  grantUrl: permission.grant,
@@ -1520,7 +1656,7 @@ class PermissionsController extends BaseController {
1520
1656
  * @param params - Parameters for adding and trusting the server
1521
1657
  * @returns Promise resolving to TransactionResult with ServerTrustResult event data
1522
1658
  */
1523
- async submitAddAndTrustServerWithSignature(params) {
1659
+ async submitAddAndTrustServerWithSignature(params, options) {
1524
1660
  this.assertWallet();
1525
1661
  try {
1526
1662
  const nonce = await this.getServersUserNonce();
@@ -1556,7 +1692,9 @@ class PermissionsController extends BaseController {
1556
1692
  if (response.type === "error") {
1557
1693
  throw new RelayerError(response.error);
1558
1694
  }
1559
- if (response.type === "signed") {
1695
+ if (response.type === "submitted") {
1696
+ hash = response.hash;
1697
+ } else if (response.type === "signed") {
1560
1698
  hash = response.hash;
1561
1699
  } else {
1562
1700
  throw new Error("Unexpected response type from relayer");
@@ -1564,7 +1702,8 @@ class PermissionsController extends BaseController {
1564
1702
  } else {
1565
1703
  hash = await this.submitAddAndTrustServerTransaction(
1566
1704
  addAndTrustServerInput,
1567
- signature
1705
+ signature,
1706
+ options
1568
1707
  );
1569
1708
  }
1570
1709
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -1603,7 +1742,7 @@ class PermissionsController extends BaseController {
1603
1742
  * @throws {ServerUrlMismatchError} When server URL doesn't match existing registration
1604
1743
  * @throws {BlockchainError} When trust operation fails for any other reason
1605
1744
  */
1606
- async submitTrustServerWithSignature(params) {
1745
+ async submitTrustServerWithSignature(params, options) {
1607
1746
  this.assertWallet();
1608
1747
  try {
1609
1748
  const nonce = await this.getServersUserNonce();
@@ -1625,7 +1764,9 @@ class PermissionsController extends BaseController {
1625
1764
  if (response.type === "error") {
1626
1765
  throw new RelayerError(response.error);
1627
1766
  }
1628
- if (response.type === "signed") {
1767
+ if (response.type === "submitted") {
1768
+ hash = response.hash;
1769
+ } else if (response.type === "signed") {
1629
1770
  hash = response.hash;
1630
1771
  } else {
1631
1772
  throw new Error("Unexpected response type from relayer");
@@ -1633,7 +1774,8 @@ class PermissionsController extends BaseController {
1633
1774
  } else {
1634
1775
  hash = await this.submitTrustServerTransaction(
1635
1776
  trustServerInput,
1636
- signature
1777
+ signature,
1778
+ options
1637
1779
  );
1638
1780
  }
1639
1781
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -1674,7 +1816,7 @@ class PermissionsController extends BaseController {
1674
1816
  * @returns Promise resolving to TransactionResult for transaction tracking
1675
1817
  * @throws {BlockchainError} When contract submission fails
1676
1818
  */
1677
- async submitDirectUntrustTransaction(params) {
1819
+ async submitDirectUntrustTransaction(params, options) {
1678
1820
  this.assertWallet();
1679
1821
  try {
1680
1822
  const chainId = await this.context.walletClient.getChainId();
@@ -1690,7 +1832,18 @@ class PermissionsController extends BaseController {
1690
1832
  functionName: "untrustServer",
1691
1833
  args: [BigInt(params.serverId)],
1692
1834
  account,
1693
- chain: this.context.walletClient?.chain ?? null
1835
+ chain: this.context.walletClient?.chain ?? null,
1836
+ ...options?.gas && { gas: options.gas },
1837
+ ...options?.nonce && { nonce: options.nonce },
1838
+ // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
1839
+ ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
1840
+ ...options.maxFeePerGas && {
1841
+ maxFeePerGas: options.maxFeePerGas
1842
+ },
1843
+ ...options.maxPriorityFeePerGas && {
1844
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
1845
+ }
1846
+ } : options?.gasPrice && { gasPrice: options.gasPrice }
1694
1847
  });
1695
1848
  const { tx } = await import("../utils/transactionHelpers");
1696
1849
  return tx({
@@ -1717,6 +1870,7 @@ class PermissionsController extends BaseController {
1717
1870
  *
1718
1871
  * @param params - Parameters for untrusting the server
1719
1872
  * @param params.serverId - The numeric ID of the server to untrust
1873
+ * @param options - Optional transaction options for gas parameters and timeout
1720
1874
  * @returns Promise resolving to transaction hash
1721
1875
  * @throws {Error} When wallet account is not available
1722
1876
  * @throws {NonceError} When retrieving user nonce fails
@@ -1737,14 +1891,17 @@ class PermissionsController extends BaseController {
1737
1891
  * console.log('Still trusting servers:', trustedServers);
1738
1892
  * ```
1739
1893
  */
1740
- async submitUntrustServer(params) {
1894
+ async submitUntrustServer(params, options) {
1741
1895
  this.assertWallet();
1742
1896
  const nonce = await this.getServersUserNonce();
1743
1897
  const untrustServerInput = {
1744
1898
  nonce,
1745
1899
  serverId: params.serverId
1746
1900
  };
1747
- return await this.submitDirectUntrustTransaction(untrustServerInput);
1901
+ return await this.submitDirectUntrustTransaction(
1902
+ untrustServerInput,
1903
+ options
1904
+ );
1748
1905
  }
1749
1906
  /**
1750
1907
  * Untrusts a server using a signature (gasless transaction).
@@ -1780,7 +1937,9 @@ class PermissionsController extends BaseController {
1780
1937
  if (response.type === "error") {
1781
1938
  throw new RelayerError(response.error);
1782
1939
  }
1783
- if (response.type === "signed") {
1940
+ if (response.type === "submitted") {
1941
+ hash = response.hash;
1942
+ } else if (response.type === "signed") {
1784
1943
  hash = response.hash;
1785
1944
  } else {
1786
1945
  throw new Error("Unexpected response type from relayer");
@@ -2226,7 +2385,7 @@ class PermissionsController extends BaseController {
2226
2385
  * @param signature - The cryptographic signature for the transaction
2227
2386
  * @returns Promise resolving to the transaction hash
2228
2387
  */
2229
- async submitAddAndTrustServerTransaction(addAndTrustServerInput, signature) {
2388
+ async submitAddAndTrustServerTransaction(addAndTrustServerInput, signature, options) {
2230
2389
  this.assertWallet();
2231
2390
  const chainId = await this.context.walletClient.getChainId();
2232
2391
  const DataPortabilityServersAddress = getContractAddress(
@@ -2260,7 +2419,16 @@ class PermissionsController extends BaseController {
2260
2419
  formattedSignature
2261
2420
  ],
2262
2421
  account: this.context.walletClient?.account ?? this.context.userAddress,
2263
- chain: this.context.walletClient?.chain ?? null
2422
+ chain: this.context.walletClient?.chain ?? null,
2423
+ ...options && {
2424
+ gas: options.gas,
2425
+ nonce: options.nonce,
2426
+ // Use EIP-1559 gas pricing if available, otherwise legacy
2427
+ ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2428
+ maxFeePerGas: options.maxFeePerGas,
2429
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
2430
+ } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2431
+ }
2264
2432
  });
2265
2433
  return txHash;
2266
2434
  }
@@ -2271,7 +2439,7 @@ class PermissionsController extends BaseController {
2271
2439
  * @param signature - The cryptographic signature for the transaction
2272
2440
  * @returns Promise resolving to the transaction hash
2273
2441
  */
2274
- async submitTrustServerTransaction(trustServerInput, signature) {
2442
+ async submitTrustServerTransaction(trustServerInput, signature, options) {
2275
2443
  this.assertWallet();
2276
2444
  const chainId = await this.context.walletClient.getChainId();
2277
2445
  const DataPortabilityServersAddress = getContractAddress(
@@ -2292,7 +2460,8 @@ class PermissionsController extends BaseController {
2292
2460
  formattedSignature
2293
2461
  ],
2294
2462
  account: this.context.walletClient?.account ?? this.context.userAddress,
2295
- chain: this.context.walletClient?.chain ?? null
2463
+ chain: this.context.walletClient?.chain ?? null,
2464
+ ...this.spreadTransactionOptions(options)
2296
2465
  });
2297
2466
  return txHash;
2298
2467
  }
@@ -2303,7 +2472,7 @@ class PermissionsController extends BaseController {
2303
2472
  * @param signature - The cryptographic signature authorizing the revoke
2304
2473
  * @returns Promise resolving to the transaction hash
2305
2474
  */
2306
- async submitDirectRevokeTransaction(typedData, signature) {
2475
+ async submitDirectRevokeTransaction(typedData, signature, options) {
2307
2476
  this.assertWallet();
2308
2477
  const chainId = await this.context.walletClient.getChainId();
2309
2478
  const DataPortabilityPermissionsAddress = getContractAddress(
@@ -2318,7 +2487,16 @@ class PermissionsController extends BaseController {
2318
2487
  functionName: "revokePermissionWithSignature",
2319
2488
  args: [typedData.message, formattedSignature],
2320
2489
  account: this.context.walletClient?.account ?? this.context.userAddress,
2321
- chain: this.context.walletClient?.chain ?? null
2490
+ chain: this.context.walletClient?.chain ?? null,
2491
+ ...options && {
2492
+ gas: options.gas,
2493
+ nonce: options.nonce,
2494
+ // Use EIP-1559 gas pricing if available, otherwise legacy
2495
+ ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2496
+ maxFeePerGas: options.maxFeePerGas,
2497
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
2498
+ } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2499
+ }
2322
2500
  });
2323
2501
  return txHash;
2324
2502
  }
@@ -2329,7 +2507,7 @@ class PermissionsController extends BaseController {
2329
2507
  * @param signature - The cryptographic signature authorizing the untrust
2330
2508
  * @returns Promise resolving to the transaction hash
2331
2509
  */
2332
- async submitSignedUntrustTransaction(typedData, signature) {
2510
+ async submitSignedUntrustTransaction(typedData, signature, options) {
2333
2511
  this.assertWallet();
2334
2512
  const chainId = await this.context.walletClient.getChainId();
2335
2513
  const DataPortabilityServersAddress = getContractAddress(
@@ -2348,7 +2526,16 @@ class PermissionsController extends BaseController {
2348
2526
  functionName: "untrustServerWithSignature",
2349
2527
  args: [contractMessage, formattedSignature],
2350
2528
  account: this.context.walletClient?.account ?? this.context.userAddress,
2351
- chain: this.context.walletClient?.chain ?? null
2529
+ chain: this.context.walletClient?.chain ?? null,
2530
+ ...options && {
2531
+ gas: options.gas,
2532
+ nonce: options.nonce,
2533
+ // Use EIP-1559 gas pricing if available, otherwise legacy
2534
+ ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2535
+ maxFeePerGas: options.maxFeePerGas,
2536
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
2537
+ } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2538
+ }
2352
2539
  });
2353
2540
  return txHash;
2354
2541
  }
@@ -2361,14 +2548,18 @@ class PermissionsController extends BaseController {
2361
2548
  * A grantee is an entity (like an application) that can receive data permissions
2362
2549
  * from users. Once registered, users can grant the grantee access to their data.
2363
2550
  *
2551
+ * This method supports gasless transactions via relayer when configured.
2552
+ * If no relayer is available, it falls back to direct wallet transactions.
2553
+ *
2364
2554
  * @param params - Parameters for registering the grantee
2365
2555
  * @param params.owner - The Ethereum address that will own this grantee registration
2366
2556
  * @param params.granteeAddress - The Ethereum address of the grantee (application)
2367
2557
  * @param params.publicKey - The public key used for data encryption/decryption (hex string)
2558
+ * @param options - Optional transaction options for gas parameters and timeout
2368
2559
  * @returns Promise resolving to the transaction hash
2369
2560
  * @throws {BlockchainError} When the grantee registration transaction fails
2370
2561
  * @throws {UserRejectedRequestError} When user rejects the transaction
2371
- * @throws {ContractError} When grantee is already registered
2562
+ * @throws {RelayerError} When gasless transaction submission fails
2372
2563
  *
2373
2564
  * @example
2374
2565
  * ```typescript
@@ -2380,36 +2571,88 @@ class PermissionsController extends BaseController {
2380
2571
  * console.log(`Grantee registered in transaction: ${txHash}`);
2381
2572
  * ```
2382
2573
  */
2383
- async submitRegisterGrantee(params) {
2384
- this.assertWallet();
2385
- const chainId = await this.context.walletClient.getChainId();
2386
- const DataPortabilityGranteesAddress = getContractAddress(
2387
- chainId,
2388
- "DataPortabilityGrantees"
2389
- );
2390
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
2391
- const ownerAddress = getAddress(params.owner);
2392
- const granteeAddress = getAddress(params.granteeAddress);
2393
- const account = this.context.walletClient?.account ?? this.context.userAddress;
2394
- const txHash = await this.context.walletClient.writeContract({
2395
- address: DataPortabilityGranteesAddress,
2396
- abi: DataPortabilityGranteesAbi,
2397
- functionName: "registerGrantee",
2398
- args: [ownerAddress, granteeAddress, params.publicKey],
2399
- account,
2400
- chain: this.context.walletClient?.chain ?? null
2401
- });
2402
- const { tx } = await import("../utils/transactionHelpers");
2403
- return tx({
2404
- hash: txHash,
2405
- from: typeof account === "string" ? account : account.address,
2406
- contract: "DataPortabilityGrantees",
2407
- fn: "registerGrantee"
2408
- });
2574
+ async submitRegisterGrantee(params, options) {
2575
+ try {
2576
+ let hash;
2577
+ if (this.context.relayer) {
2578
+ const request = {
2579
+ type: "direct",
2580
+ operation: "submitRegisterGrantee",
2581
+ params: {
2582
+ owner: params.owner,
2583
+ granteeAddress: params.granteeAddress,
2584
+ publicKey: params.publicKey
2585
+ }
2586
+ };
2587
+ const response = await this.context.relayer(request);
2588
+ if (response.type === "error") {
2589
+ throw new RelayerError(response.error);
2590
+ }
2591
+ if (response.type === "submitted") {
2592
+ hash = response.hash;
2593
+ } else if (response.type === "direct") {
2594
+ const result = response.result;
2595
+ hash = result.transactionHash;
2596
+ } else {
2597
+ throw new Error("Unexpected response type from relayer");
2598
+ }
2599
+ } else {
2600
+ this.assertWallet();
2601
+ const chainId = await this.context.walletClient.getChainId();
2602
+ const DataPortabilityGranteesAddress = getContractAddress(
2603
+ chainId,
2604
+ "DataPortabilityGrantees"
2605
+ );
2606
+ const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
2607
+ const ownerAddress = getAddress(params.owner);
2608
+ const granteeAddress = getAddress(params.granteeAddress);
2609
+ const account2 = this.context.walletClient?.account ?? this.context.userAddress;
2610
+ hash = await this.context.walletClient.writeContract({
2611
+ address: DataPortabilityGranteesAddress,
2612
+ abi: DataPortabilityGranteesAbi,
2613
+ functionName: "registerGrantee",
2614
+ args: [ownerAddress, granteeAddress, params.publicKey],
2615
+ account: account2,
2616
+ chain: this.context.walletClient?.chain ?? null,
2617
+ ...this.spreadTransactionOptions(options)
2618
+ });
2619
+ }
2620
+ const account = this.context.walletClient?.account ?? this.context.userAddress;
2621
+ const { tx } = await import("../utils/transactionHelpers");
2622
+ return tx({
2623
+ hash,
2624
+ from: typeof account === "string" ? account : account.address,
2625
+ contract: "DataPortabilityGrantees",
2626
+ fn: "registerGrantee"
2627
+ });
2628
+ } catch (error) {
2629
+ if (error instanceof Error) {
2630
+ if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof BlockchainError) {
2631
+ throw error;
2632
+ }
2633
+ if (error.name === "ContractFunctionExecutionError") {
2634
+ throw new BlockchainError(
2635
+ `Grantee registration failed: ${error.message}`,
2636
+ error
2637
+ );
2638
+ }
2639
+ if (error.name === "UserRejectedRequestError") {
2640
+ throw new UserRejectedRequestError(
2641
+ "User rejected the grantee registration transaction"
2642
+ );
2643
+ }
2644
+ throw new BlockchainError(
2645
+ `Failed to register grantee: ${error.message}`,
2646
+ error
2647
+ );
2648
+ }
2649
+ throw new BlockchainError(`Failed to register grantee: ${String(error)}`);
2650
+ }
2409
2651
  }
2410
2652
  // TODO: When DataPortabilityGrantees contract adds registerGranteeWithSignature function,
2411
2653
  // implement submitRegisterGranteeWithSignature and submitSignedRegisterGrantee methods
2412
- // to support gasless transactions via relayer
2654
+ // to support EIP-712 signed gasless transactions via relayer.
2655
+ // Current implementation above supports direct gasless transactions (relayer pays gas directly).
2413
2656
  /**
2414
2657
  * Retrieves all registered grantees from the DataPortabilityGrantees contract.
2415
2658
  *
@@ -2457,27 +2700,52 @@ class PermissionsController extends BaseController {
2457
2700
  const total = Number(totalCount);
2458
2701
  const limit = options.limit ?? 50;
2459
2702
  const offset = options.offset ?? 0;
2460
- const grantees = [];
2461
- const endIndex = Math.min(offset + limit, total);
2462
- for (let i = offset; i < endIndex; i++) {
2463
- try {
2464
- const granteeInfo = await this.context.publicClient.readContract({
2465
- address: DataPortabilityGranteesAddress,
2466
- abi: DataPortabilityGranteesAbi,
2467
- functionName: "grantees",
2468
- args: [BigInt(i + 1)]
2469
- // Grantee IDs are 1-indexed
2470
- });
2471
- grantees.push({
2472
- id: i + 1,
2473
- owner: granteeInfo.owner,
2474
- address: granteeInfo.granteeAddress,
2475
- publicKey: granteeInfo.publicKey,
2476
- permissionIds: granteeInfo.permissionIds.map((id) => Number(id))
2477
- });
2478
- } catch (error) {
2479
- console.warn(`Failed to fetch grantee ${i + 1}:`, error);
2480
- }
2703
+ const includePermissions = options.includePermissions ?? true;
2704
+ const startId = total - offset;
2705
+ const endId = Math.max(startId - limit + 1, 1);
2706
+ const granteeIds = Array.from(
2707
+ { length: startId - endId + 1 },
2708
+ (_, i) => startId - i
2709
+ // Generate IDs in descending order
2710
+ );
2711
+ let grantees;
2712
+ if (includePermissions) {
2713
+ const granteePromises = granteeIds.map(
2714
+ (granteeId) => this.getGranteeById(granteeId)
2715
+ );
2716
+ const granteeResults = await Promise.all(granteePromises);
2717
+ grantees = granteeResults.filter(
2718
+ (grantee) => grantee !== null
2719
+ );
2720
+ } else {
2721
+ const granteeInfoPromises = granteeIds.map(
2722
+ async (granteeId) => {
2723
+ try {
2724
+ const granteeInfo = await this.context.publicClient.readContract({
2725
+ address: DataPortabilityGranteesAddress,
2726
+ abi: DataPortabilityGranteesAbi,
2727
+ functionName: "granteesV2",
2728
+ args: [BigInt(granteeId)]
2729
+ });
2730
+ const grantee = {
2731
+ id: granteeId,
2732
+ owner: granteeInfo.owner,
2733
+ address: granteeInfo.granteeAddress,
2734
+ publicKey: granteeInfo.publicKey,
2735
+ permissionIds: []
2736
+ // TypeScript infers number[] from Grantee type
2737
+ };
2738
+ return grantee;
2739
+ } catch (error) {
2740
+ console.warn(`Failed to fetch grantee ${granteeId}:`, error);
2741
+ return null;
2742
+ }
2743
+ }
2744
+ );
2745
+ const granteeInfoResults = await Promise.all(granteeInfoPromises);
2746
+ grantees = granteeInfoResults.filter(
2747
+ (grantee) => grantee !== null
2748
+ );
2481
2749
  }
2482
2750
  return {
2483
2751
  grantees,
@@ -2488,15 +2756,16 @@ class PermissionsController extends BaseController {
2488
2756
  };
2489
2757
  }
2490
2758
  /**
2491
- * Retrieves a specific grantee by their Ethereum address from the DataPortabilityGrantees contract.
2759
+ * Retrieves a specific grantee by their Ethereum wallet address.
2492
2760
  *
2761
+ * @remarks
2493
2762
  * Looks up a registered grantee (application) using their Ethereum address
2494
- * and returns their complete registration information including permissions.
2763
+ * and returns their complete registration information including all associated permissions.
2495
2764
  *
2496
- * @param granteeAddress - The Ethereum address of the grantee to look up
2497
- * @returns Promise resolving to the grantee information, or null if not found
2498
- * @throws {BlockchainError} When contract read operation fails
2499
- * @throws {NetworkError} When unable to connect to the blockchain network
2765
+ * Returns `null` if the address is not registered as a grantee or if an error occurs.
2766
+ *
2767
+ * @param granteeAddress - Ethereum wallet address of the grantee to query
2768
+ * @returns Grantee information including ID, addresses, public key, and permission IDs, or `null` if not found
2500
2769
  *
2501
2770
  * @example
2502
2771
  * ```typescript
@@ -2521,40 +2790,32 @@ class PermissionsController extends BaseController {
2521
2790
  );
2522
2791
  const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
2523
2792
  try {
2524
- const granteeInfo = await this.context.publicClient.readContract({
2525
- address: DataPortabilityGranteesAddress,
2526
- abi: DataPortabilityGranteesAbi,
2527
- functionName: "granteeByAddress",
2528
- args: [granteeAddress]
2529
- });
2530
2793
  const granteeId = await this.context.publicClient.readContract({
2531
2794
  address: DataPortabilityGranteesAddress,
2532
2795
  abi: DataPortabilityGranteesAbi,
2533
2796
  functionName: "granteeAddressToId",
2534
2797
  args: [granteeAddress]
2535
2798
  });
2536
- return {
2537
- id: Number(granteeId),
2538
- owner: granteeInfo.owner,
2539
- address: granteeInfo.granteeAddress,
2540
- publicKey: granteeInfo.publicKey,
2541
- permissionIds: granteeInfo.permissionIds.map((id) => Number(id))
2542
- };
2799
+ if (granteeId === 0n) {
2800
+ return null;
2801
+ }
2802
+ return await this.getGranteeById(Number(granteeId));
2543
2803
  } catch (error) {
2544
2804
  console.warn(`Failed to fetch grantee ${granteeAddress}:`, error);
2545
2805
  return null;
2546
2806
  }
2547
2807
  }
2548
2808
  /**
2549
- * Retrieves a specific grantee by their unique ID from the DataPortabilityGrantees contract.
2809
+ * Retrieves a specific grantee by their unique ID.
2550
2810
  *
2811
+ * @remarks
2551
2812
  * Looks up a registered grantee (application) using their numeric ID assigned during
2552
- * registration and returns their complete information including permissions.
2813
+ * registration and returns their complete information including all associated permissions.
2553
2814
  *
2554
- * @param granteeId - The unique numeric ID of the grantee (1-indexed)
2555
- * @returns Promise resolving to the grantee information, or null if not found
2556
- * @throws {BlockchainError} When contract read operation fails
2557
- * @throws {NetworkError} When unable to connect to the blockchain network
2815
+ * Returns `null` if the grantee is not found or if an error occurs during fetching.
2816
+ *
2817
+ * @param granteeId - Unique numeric ID of the grantee (1-indexed)
2818
+ * @returns Grantee information including ID, addresses, public key, and permission IDs, or `null` if not found
2558
2819
  *
2559
2820
  * @example
2560
2821
  * ```typescript
@@ -2562,7 +2823,7 @@ class PermissionsController extends BaseController {
2562
2823
  *
2563
2824
  * if (grantee) {
2564
2825
  * console.log(`Grantee ID: ${grantee.id}`);
2565
- * console.log(`Address: ${grantee.granteeAddress}`);
2826
+ * console.log(`Address: ${grantee.address}`);
2566
2827
  * console.log(`Owner: ${grantee.owner}`);
2567
2828
  * console.log(`Total permissions: ${grantee.permissionIds.length}`);
2568
2829
  * } else {
@@ -2578,18 +2839,23 @@ class PermissionsController extends BaseController {
2578
2839
  );
2579
2840
  const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
2580
2841
  try {
2581
- const granteeInfo = await this.context.publicClient.readContract({
2842
+ const granteeInfoResult = await this.context.publicClient.readContract({
2582
2843
  address: DataPortabilityGranteesAddress,
2583
2844
  abi: DataPortabilityGranteesAbi,
2584
- functionName: "grantees",
2845
+ functionName: "granteesV2",
2585
2846
  args: [BigInt(granteeId)]
2586
2847
  });
2848
+ const granteeInfo = granteeInfoResult;
2849
+ const allPermissionIdsResult = await this.getGranteePermissionsPaginated(
2850
+ BigInt(granteeId)
2851
+ );
2852
+ const allPermissionIds = allPermissionIdsResult;
2587
2853
  return {
2588
2854
  id: granteeId,
2589
2855
  owner: granteeInfo.owner,
2590
2856
  address: granteeInfo.granteeAddress,
2591
2857
  publicKey: granteeInfo.publicKey,
2592
- permissionIds: granteeInfo.permissionIds.map((id) => Number(id))
2858
+ permissionIds: allPermissionIds.map((id) => Number(id))
2593
2859
  };
2594
2860
  } catch (error) {
2595
2861
  console.warn(`Failed to fetch grantee ${granteeId}:`, error);
@@ -2986,6 +3252,31 @@ class PermissionsController extends BaseController {
2986
3252
  );
2987
3253
  }
2988
3254
  }
3255
+ /**
3256
+ * Retrieves detailed grant file data from IPFS or HTTP storage.
3257
+ *
3258
+ * @remarks
3259
+ * This method automatically uses the SDK's configured downloadRelayer to bypass CORS restrictions.
3260
+ * Use this instead of importing the standalone `retrieveGrantFile` utility.
3261
+ *
3262
+ * @param grantUrl - The grant file URL (from OnChainPermissionGrant.grantUrl)
3263
+ * @returns Promise resolving to the complete grant file with operation details
3264
+ * @throws {NetworkError} When all retrieval attempts fail
3265
+ * @example
3266
+ * ```typescript
3267
+ * const grants = await vana.permissions.getUserPermissionGrantsOnChain();
3268
+ * const grantFile = await vana.permissions.retrieveGrantFile(grants[0].grantUrl);
3269
+ * console.log(`Operation: ${grantFile.operation}`);
3270
+ * ```
3271
+ */
3272
+ async retrieveGrantFile(grantUrl) {
3273
+ const { retrieveGrantFile: retrieveGrantFileUtil } = await import("../utils/grantFiles");
3274
+ return retrieveGrantFileUtil(
3275
+ grantUrl,
3276
+ void 0,
3277
+ this.context.downloadRelayer
3278
+ );
3279
+ }
2989
3280
  /**
2990
3281
  * Get all permissions for a specific file (alias for getFilePermissionIds)
2991
3282
  *
@@ -3011,26 +3302,34 @@ class PermissionsController extends BaseController {
3011
3302
  // DATA PORTABILITY GRANTEES HELPER METHODS
3012
3303
  // ===========================
3013
3304
  /**
3014
- * Get grantee information by grantee ID
3305
+ * Retrieves detailed grantee information including all associated permissions.
3306
+ *
3307
+ * @remarks
3308
+ * Returns grantee metadata and associated permission IDs. Uses the newer
3309
+ * paginated contract method internally for efficient permission fetching.
3015
3310
  *
3016
- * @param granteeId - Grantee ID to get info for
3017
- * @returns Promise resolving to grantee info
3311
+ * @param granteeId - Unique grantee identifier as bigint
3312
+ * @returns Grantee information containing owner address, grantee address, public key, and permission IDs
3313
+ * @throws {BlockchainError} When grantee ID is not found or contract read fails
3314
+ *
3315
+ * @example
3316
+ * ```typescript
3317
+ * const granteeInfo = await vana.permissions.getGranteeInfo(BigInt(1));
3318
+ * console.log(`Grantee ${granteeInfo.granteeAddress} has ${granteeInfo.permissionIds.length} permissions`);
3319
+ * ```
3018
3320
  */
3019
3321
  async getGranteeInfo(granteeId) {
3020
3322
  try {
3021
- const chainId = await this.context.publicClient.getChainId();
3022
- const DataPortabilityGranteesAddress = getContractAddress(
3023
- chainId,
3024
- "DataPortabilityGrantees"
3025
- );
3026
- const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
3027
- const granteeInfo = await this.context.publicClient.readContract({
3028
- address: DataPortabilityGranteesAddress,
3029
- abi: DataPortabilityGranteesAbi,
3030
- functionName: "granteeInfo",
3031
- args: [granteeId]
3032
- });
3033
- return granteeInfo;
3323
+ const grantee = await this.getGranteeById(Number(granteeId));
3324
+ if (!grantee) {
3325
+ throw new Error("Grantee not found");
3326
+ }
3327
+ return {
3328
+ owner: grantee.owner,
3329
+ granteeAddress: grantee.address,
3330
+ publicKey: grantee.publicKey,
3331
+ permissionIds: grantee.permissionIds.map((id) => BigInt(id))
3332
+ };
3034
3333
  } catch (error) {
3035
3334
  throw new BlockchainError(
3036
3335
  `Failed to get grantee info: ${error instanceof Error ? error.message : "Unknown error"}`,
@@ -3039,10 +3338,21 @@ class PermissionsController extends BaseController {
3039
3338
  }
3040
3339
  }
3041
3340
  /**
3042
- * Get grantee information by grantee address
3341
+ * Retrieves detailed grantee information by wallet address.
3043
3342
  *
3044
- * @param granteeAddress - Grantee address to get info for
3045
- * @returns Promise resolving to grantee info
3343
+ * @remarks
3344
+ * Looks up the grantee ID from the provided address, then fetches complete
3345
+ * grantee information including all associated permissions.
3346
+ *
3347
+ * @param granteeAddress - Ethereum wallet address of the grantee to query
3348
+ * @returns Grantee information containing owner address, grantee address, public key, and permission IDs
3349
+ * @throws {BlockchainError} When grantee address is not registered or contract read fails
3350
+ *
3351
+ * @example
3352
+ * ```typescript
3353
+ * const granteeInfo = await vana.permissions.getGranteeInfoByAddress("0x742d35Cc6634c0532925a3b844Bc9e8e1ee3b2De");
3354
+ * console.log(`Found grantee with ${granteeInfo.permissionIds.length} permissions`);
3355
+ * ```
3046
3356
  */
3047
3357
  async getGranteeInfoByAddress(granteeAddress) {
3048
3358
  try {
@@ -3052,13 +3362,26 @@ class PermissionsController extends BaseController {
3052
3362
  "DataPortabilityGrantees"
3053
3363
  );
3054
3364
  const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
3055
- const granteeInfo = await this.context.publicClient.readContract({
3365
+ const granteeIdResult = await this.context.publicClient.readContract({
3056
3366
  address: DataPortabilityGranteesAddress,
3057
3367
  abi: DataPortabilityGranteesAbi,
3058
- functionName: "granteeByAddress",
3368
+ functionName: "granteeAddressToId",
3059
3369
  args: [granteeAddress]
3060
3370
  });
3061
- return granteeInfo;
3371
+ const granteeId = granteeIdResult;
3372
+ if (granteeId === 0n) {
3373
+ throw new Error("Grantee not found");
3374
+ }
3375
+ const grantee = await this.getGranteeById(Number(granteeId));
3376
+ if (!grantee) {
3377
+ throw new Error("Grantee not found");
3378
+ }
3379
+ return {
3380
+ owner: grantee.owner,
3381
+ granteeAddress: grantee.address,
3382
+ publicKey: grantee.publicKey,
3383
+ permissionIds: grantee.permissionIds.map((id) => BigInt(id))
3384
+ };
3062
3385
  } catch (error) {
3063
3386
  throw new BlockchainError(
3064
3387
  `Failed to get grantee info by address: ${error instanceof Error ? error.message : "Unknown error"}`,
@@ -3122,6 +3445,117 @@ class PermissionsController extends BaseController {
3122
3445
  );
3123
3446
  }
3124
3447
  }
3448
+ /**
3449
+ * Retrieves permission IDs for a specific grantee with flexible pagination.
3450
+ *
3451
+ * @remarks
3452
+ * **Pagination Behavior:**
3453
+ * Returns different types based on parameters:
3454
+ * - Without offset/limit: Returns `bigint[]` of all permissions using batched multicall
3455
+ * - With offset/limit: Returns paginated object with `permissionIds`, `totalCount`, and `hasMore`
3456
+ *
3457
+ * Uses gas-aware multicall for efficient batch fetching when retrieving all permissions.
3458
+ *
3459
+ * @param granteeId - Grantee ID to get permissions for
3460
+ * @param options - Optional pagination parameters
3461
+ * @param options.offset - Zero-based starting index for pagination. Defaults to 0 when fetching all permissions. Required for single-page requests.
3462
+ * @param options.limit - Maximum number of permission IDs to return per page. Defaults to 100 when fetching all permissions. Required for single-page requests.
3463
+ * @returns When called without options: Array of all permission IDs as `bigint[]`.
3464
+ * When called with offset and limit: Paginated result object containing `permissionIds` array,
3465
+ * `totalCount`, and `hasMore` boolean.
3466
+ * @throws {BlockchainError} When contract read operation fails
3467
+ *
3468
+ * @example
3469
+ * ```typescript
3470
+ * // Fetch all permissions (no pagination params)
3471
+ * const allPermissions = await vana.permissions.getGranteePermissionsPaginated(BigInt(1));
3472
+ * console.log(`Total permissions: ${allPermissions.length}`);
3473
+ *
3474
+ * // Fetch a specific page (with pagination params)
3475
+ * const page = await vana.permissions.getGranteePermissionsPaginated(BigInt(1), {
3476
+ * offset: BigInt(0),
3477
+ * limit: BigInt(100)
3478
+ * });
3479
+ * console.log(`Fetched ${page.permissionIds.length} permissions`);
3480
+ * console.log(`Total: ${page.totalCount}, Has more: ${page.hasMore}`);
3481
+ *
3482
+ * // Fetch next page
3483
+ * if (page.hasMore) {
3484
+ * const nextPage = await vana.permissions.getGranteePermissionsPaginated(BigInt(1), {
3485
+ * offset: BigInt(100),
3486
+ * limit: BigInt(100)
3487
+ * });
3488
+ * }
3489
+ * ```
3490
+ */
3491
+ async getGranteePermissionsPaginated(granteeId, options) {
3492
+ try {
3493
+ const chainId = await this.context.publicClient.getChainId();
3494
+ const DataPortabilityGranteesAddress = getContractAddress(
3495
+ chainId,
3496
+ "DataPortabilityGrantees"
3497
+ );
3498
+ const DataPortabilityGranteesAbi = getAbi("DataPortabilityGrantees");
3499
+ const fetchOnlyOnePage = options?.offset !== void 0 && options?.limit !== void 0;
3500
+ if (fetchOnlyOnePage) {
3501
+ const result = await this.context.publicClient.readContract({
3502
+ address: DataPortabilityGranteesAddress,
3503
+ abi: DataPortabilityGranteesAbi,
3504
+ functionName: "granteePermissionsPaginated",
3505
+ args: [granteeId, options.offset, options.limit]
3506
+ });
3507
+ const [permissionIds, totalCount2, hasMore] = result;
3508
+ return {
3509
+ permissionIds: [...permissionIds],
3510
+ totalCount: totalCount2,
3511
+ hasMore
3512
+ };
3513
+ }
3514
+ const countResult = await this.context.publicClient.readContract({
3515
+ address: DataPortabilityGranteesAddress,
3516
+ abi: DataPortabilityGranteesAbi,
3517
+ functionName: "granteePermissionsPaginated",
3518
+ args: [granteeId, BigInt(0), BigInt(1)]
3519
+ });
3520
+ const [, totalCount] = countResult;
3521
+ if (totalCount === BigInt(0)) {
3522
+ return [];
3523
+ }
3524
+ const batchSize = options?.limit ?? BigInt(100);
3525
+ const startOffset = options?.offset ?? BigInt(0);
3526
+ const endOffset = totalCount;
3527
+ const numBatches = Math.ceil(
3528
+ Number(endOffset - startOffset) / Number(batchSize)
3529
+ );
3530
+ const paginationCalls = Array.from({ length: numBatches }, (_, i) => ({
3531
+ address: DataPortabilityGranteesAddress,
3532
+ abi: DataPortabilityGranteesAbi,
3533
+ functionName: "granteePermissionsPaginated",
3534
+ args: [
3535
+ granteeId,
3536
+ startOffset + BigInt(i) * batchSize,
3537
+ batchSize
3538
+ ]
3539
+ }));
3540
+ const results = await gasAwareMulticall(
3541
+ this.context.publicClient,
3542
+ {
3543
+ contracts: paginationCalls
3544
+ }
3545
+ );
3546
+ const allPermissionIds = [];
3547
+ for (const result of results) {
3548
+ const [permissionIds] = result;
3549
+ allPermissionIds.push(...permissionIds);
3550
+ }
3551
+ return allPermissionIds;
3552
+ } catch (error) {
3553
+ throw new BlockchainError(
3554
+ `Failed to get grantee permissions: ${error instanceof Error ? error.message : "Unknown error"}`,
3555
+ error
3556
+ );
3557
+ }
3558
+ }
3125
3559
  // ===== DataPortabilityServersImplementation Methods =====
3126
3560
  /**
3127
3561
  * Get all server IDs for a user
@@ -3315,9 +3749,10 @@ class PermissionsController extends BaseController {
3315
3749
  *
3316
3750
  * @param serverId - Server ID to update
3317
3751
  * @param url - New URL for the server
3752
+ * @param options - Optional transaction options for gas parameters and timeout
3318
3753
  * @returns Promise resolving to transaction hash
3319
3754
  */
3320
- async submitUpdateServer(serverId, url) {
3755
+ async submitUpdateServer(serverId, url, options) {
3321
3756
  this.assertWallet();
3322
3757
  try {
3323
3758
  const chainId = await this.context.walletClient.getChainId();
@@ -3333,7 +3768,18 @@ class PermissionsController extends BaseController {
3333
3768
  functionName: "updateServer",
3334
3769
  args: [serverId, url],
3335
3770
  chain: this.context.walletClient?.chain,
3336
- account
3771
+ account,
3772
+ ...options?.gas && { gas: options.gas },
3773
+ ...options?.nonce && { nonce: options.nonce },
3774
+ // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
3775
+ ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
3776
+ ...options.maxFeePerGas && {
3777
+ maxFeePerGas: options.maxFeePerGas
3778
+ },
3779
+ ...options.maxPriorityFeePerGas && {
3780
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
3781
+ }
3782
+ } : options?.gasPrice && { gasPrice: options.gasPrice }
3337
3783
  });
3338
3784
  const { tx } = await import("../utils/transactionHelpers");
3339
3785
  return tx({
@@ -3529,7 +3975,7 @@ class PermissionsController extends BaseController {
3529
3975
  * @throws {BlockchainError} When permission addition fails
3530
3976
  * @throws {NetworkError} When network communication fails
3531
3977
  */
3532
- async submitSignedAddPermission(typedData, signature) {
3978
+ async submitSignedAddPermission(typedData, signature, options) {
3533
3979
  this.assertWallet();
3534
3980
  try {
3535
3981
  let hash;
@@ -3544,7 +3990,9 @@ class PermissionsController extends BaseController {
3544
3990
  if (response.type === "error") {
3545
3991
  throw new RelayerError(response.error);
3546
3992
  }
3547
- if (response.type === "signed") {
3993
+ if (response.type === "submitted") {
3994
+ hash = response.hash;
3995
+ } else if (response.type === "signed") {
3548
3996
  hash = response.hash;
3549
3997
  } else {
3550
3998
  throw new Error("Unexpected response type from relayer");
@@ -3552,7 +4000,8 @@ class PermissionsController extends BaseController {
3552
4000
  } else {
3553
4001
  hash = await this.submitDirectAddPermissionTransaction(
3554
4002
  typedData,
3555
- signature
4003
+ signature,
4004
+ options
3556
4005
  );
3557
4006
  }
3558
4007
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -3593,6 +4042,9 @@ class PermissionsController extends BaseController {
3593
4042
  * @param params.serverPublicKey - Server's public key for encryption.
3594
4043
  * Obtain via `vana.server.getIdentity(userAddress).publicKey`.
3595
4044
  * @param params.filePermissions - Nested array of permissions for each file
4045
+ * @param options - Optional transaction options for gas parameters and timeout.
4046
+ * Note: These options are only applied for direct blockchain transactions.
4047
+ * When using relayer callbacks (gasless transactions), these options are ignored.
3596
4048
  * @returns TransactionResult with immediate hash access and optional event data
3597
4049
  * @throws {Error} When schemaIds array length doesn't match fileUrls array length
3598
4050
  * @throws {SchemaValidationError} When file data doesn't match the specified schema.
@@ -3606,6 +4058,7 @@ class PermissionsController extends BaseController {
3606
4058
  *
3607
4059
  * @example
3608
4060
  * ```typescript
4061
+ * // Submit with custom gas parameters and timeout
3609
4062
  * const result = await vana.permissions.submitAddServerFilesAndPermissions({
3610
4063
  * granteeId: BigInt(1),
3611
4064
  * grant: "ipfs://QmXxx...",
@@ -3618,12 +4071,19 @@ class PermissionsController extends BaseController {
3618
4071
  * account: "0x742d35Cc6634C0532925a3b844Bc9e7595f0b0Bb",
3619
4072
  * key: encryptedKey
3620
4073
  * }]]
4074
+ * }, {
4075
+ * maxFeePerGas: 100n * 10n ** 9n, // 100 gwei
4076
+ * maxPriorityFeePerGas: 2n * 10n ** 9n, // 2 gwei tip
4077
+ * });
4078
+ *
4079
+ * // Wait for confirmation with custom timeout
4080
+ * const receipt = await vana.waitForTransactionReceipt(result, {
4081
+ * timeout: 180000 // 3 minutes
3621
4082
  * });
3622
- * const events = await result.waitForEvents();
3623
- * console.log(`Permission ID: ${events.permissionId}`);
4083
+ * console.log(`Transaction confirmed: ${receipt.transactionHash}`);
3624
4084
  * ```
3625
4085
  */
3626
- async submitAddServerFilesAndPermissions(params) {
4086
+ async submitAddServerFilesAndPermissions(params, options) {
3627
4087
  this.assertWallet();
3628
4088
  try {
3629
4089
  if (params.schemaIds.length !== params.fileUrls.length) {
@@ -3649,7 +4109,8 @@ class PermissionsController extends BaseController {
3649
4109
  const signature = await this.signTypedData(typedData);
3650
4110
  return await this.submitSignedAddServerFilesAndPermissions(
3651
4111
  typedData,
3652
- signature
4112
+ signature,
4113
+ options
3653
4114
  );
3654
4115
  } catch (error) {
3655
4116
  if (error instanceof RelayerError || error instanceof UserRejectedRequestError || error instanceof SerializationError || error instanceof SignatureError || error instanceof NetworkError || error instanceof NonceError) {
@@ -3670,6 +4131,9 @@ class PermissionsController extends BaseController {
3670
4131
  *
3671
4132
  * @param typedData - The EIP-712 typed data for AddServerFilesAndPermissions
3672
4133
  * @param signature - The user's signature
4134
+ * @param options - Optional transaction options for gas parameters and timeout.
4135
+ * Note: These options are only applied for direct blockchain transactions.
4136
+ * When using relayer callbacks (gasless transactions), these options are ignored.
3673
4137
  * @returns TransactionResult with immediate hash access and optional event data
3674
4138
  * @throws {RelayerError} When gasless transaction submission fails
3675
4139
  * @throws {BlockchainError} When server files and permissions addition fails
@@ -3688,7 +4152,7 @@ class PermissionsController extends BaseController {
3688
4152
  * console.log(`Permission created with ID: ${permissionId}`);
3689
4153
  * ```
3690
4154
  */
3691
- async submitSignedAddServerFilesAndPermissions(typedData, signature) {
4155
+ async submitSignedAddServerFilesAndPermissions(typedData, signature, options) {
3692
4156
  this.assertWallet();
3693
4157
  try {
3694
4158
  let hash;
@@ -3706,7 +4170,9 @@ class PermissionsController extends BaseController {
3706
4170
  if (response.type === "error") {
3707
4171
  throw new RelayerError(response.error);
3708
4172
  }
3709
- if (response.type === "signed") {
4173
+ if (response.type === "submitted") {
4174
+ hash = response.hash;
4175
+ } else if (response.type === "signed") {
3710
4176
  hash = response.hash;
3711
4177
  } else {
3712
4178
  throw new Error("Unexpected response type from relayer");
@@ -3717,7 +4183,8 @@ class PermissionsController extends BaseController {
3717
4183
  );
3718
4184
  hash = await this.submitDirectAddServerFilesAndPermissionsTransaction(
3719
4185
  typedData,
3720
- signature
4186
+ signature,
4187
+ options
3721
4188
  );
3722
4189
  }
3723
4190
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -3742,9 +4209,10 @@ class PermissionsController extends BaseController {
3742
4209
  * Submit permission revocation with signature to the blockchain
3743
4210
  *
3744
4211
  * @param permissionId - Permission ID to revoke
4212
+ * @param options - Optional transaction options for gas parameters and timeout
3745
4213
  * @returns Promise resolving to transaction hash
3746
4214
  */
3747
- async submitRevokePermission(permissionId) {
4215
+ async submitRevokePermission(permissionId, options) {
3748
4216
  this.assertWallet();
3749
4217
  try {
3750
4218
  const chainId = await this.context.walletClient.getChainId();
@@ -3765,7 +4233,18 @@ class PermissionsController extends BaseController {
3765
4233
  functionName: "revokePermission",
3766
4234
  args: [permissionId],
3767
4235
  chain: this.context.walletClient?.chain,
3768
- account
4236
+ account,
4237
+ ...options?.gas && { gas: options.gas },
4238
+ ...options?.nonce && { nonce: options.nonce },
4239
+ // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
4240
+ ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
4241
+ ...options.maxFeePerGas && {
4242
+ maxFeePerGas: options.maxFeePerGas
4243
+ },
4244
+ ...options.maxPriorityFeePerGas && {
4245
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
4246
+ }
4247
+ } : options?.gasPrice && { gasPrice: options.gasPrice }
3769
4248
  });
3770
4249
  const { tx } = await import("../utils/transactionHelpers");
3771
4250
  return tx({
@@ -3788,7 +4267,7 @@ class PermissionsController extends BaseController {
3788
4267
  * @param signature - The cryptographic signature authorizing the transaction
3789
4268
  * @returns Promise resolving to the transaction hash
3790
4269
  */
3791
- async submitDirectAddPermissionTransaction(typedData, signature) {
4270
+ async submitDirectAddPermissionTransaction(typedData, signature, options) {
3792
4271
  this.assertWallet();
3793
4272
  const chainId = await this.context.walletClient.getChainId();
3794
4273
  const DataPortabilityPermissionsAddress = getContractAddress(
@@ -3809,7 +4288,8 @@ class PermissionsController extends BaseController {
3809
4288
  functionName: "addPermission",
3810
4289
  args: [permissionInput, formattedSignature],
3811
4290
  account: this.context.walletClient?.account ?? this.context.userAddress,
3812
- chain: this.context.walletClient?.chain ?? null
4291
+ chain: this.context.walletClient?.chain ?? null,
4292
+ ...this.spreadTransactionOptions(options)
3813
4293
  });
3814
4294
  return hash;
3815
4295
  }
@@ -3820,7 +4300,7 @@ class PermissionsController extends BaseController {
3820
4300
  * @param signature - The cryptographic signature authorizing the transaction
3821
4301
  * @returns Promise resolving to the transaction hash
3822
4302
  */
3823
- async submitDirectAddServerFilesAndPermissionsTransaction(typedData, signature) {
4303
+ async submitDirectAddServerFilesAndPermissionsTransaction(typedData, signature, options) {
3824
4304
  this.assertWallet();
3825
4305
  const chainId = await this.context.publicClient.getChainId();
3826
4306
  const DataPortabilityPermissionsAddress = getContractAddress(
@@ -3844,10 +4324,11 @@ class PermissionsController extends BaseController {
3844
4324
  address: DataPortabilityPermissionsAddress,
3845
4325
  abi: DataPortabilityPermissionsAbi,
3846
4326
  functionName: "addServerFilesAndPermissions",
3847
- // @ts-expect-error - Viem's type inference for nested Permission[][] arrays is incompatible with our Permission type
3848
4327
  args: [serverFilesAndPermissionInput, formattedSignature],
3849
4328
  account: this.context.walletClient?.account ?? this.context.userAddress,
3850
- chain: this.context.walletClient?.chain ?? null
4329
+ chain: this.context.walletClient?.chain ?? null,
4330
+ ...options?.value && { value: options.value },
4331
+ ...this.spreadTransactionOptions(options)
3851
4332
  });
3852
4333
  return hash;
3853
4334
  }