@opendatalabs/vana-sdk 0.1.0-alpha.a6b60fc → 0.1.0-alpha.a78ce5c

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 (256) hide show
  1. package/dist/client/__tests__/enhancedResponse.test.d.ts +1 -0
  2. package/dist/client/enhancedResponse.cjs +164 -0
  3. package/dist/client/enhancedResponse.cjs.map +1 -0
  4. package/dist/client/enhancedResponse.d.ts +120 -0
  5. package/dist/client/enhancedResponse.js +138 -0
  6. package/dist/client/enhancedResponse.js.map +1 -0
  7. package/dist/controllers/__tests__/data-consistency-integration.test.d.ts +7 -0
  8. package/dist/controllers/__tests__/operations.processQueue.test.d.ts +1 -0
  9. package/dist/controllers/base.cjs +33 -0
  10. package/dist/controllers/base.cjs.map +1 -1
  11. package/dist/controllers/base.d.ts +10 -0
  12. package/dist/controllers/base.js +33 -0
  13. package/dist/controllers/base.js.map +1 -1
  14. package/dist/controllers/data.cjs +278 -159
  15. package/dist/controllers/data.cjs.map +1 -1
  16. package/dist/controllers/data.d.ts +34 -19
  17. package/dist/controllers/data.js +291 -162
  18. package/dist/controllers/data.js.map +1 -1
  19. package/dist/controllers/operations.cjs +430 -0
  20. package/dist/controllers/operations.cjs.map +1 -0
  21. package/dist/controllers/operations.d.ts +229 -0
  22. package/dist/controllers/operations.js +406 -0
  23. package/dist/controllers/operations.js.map +1 -0
  24. package/dist/controllers/permissions.cjs +605 -213
  25. package/dist/controllers/permissions.cjs.map +1 -1
  26. package/dist/controllers/permissions.d.ts +141 -34
  27. package/dist/controllers/permissions.js +605 -213
  28. package/dist/controllers/permissions.js.map +1 -1
  29. package/dist/controllers/schemas.cjs +81 -4
  30. package/dist/controllers/schemas.cjs.map +1 -1
  31. package/dist/controllers/schemas.d.ts +41 -0
  32. package/dist/controllers/schemas.js +81 -4
  33. package/dist/controllers/schemas.js.map +1 -1
  34. package/dist/controllers/server.cjs +251 -42
  35. package/dist/controllers/server.cjs.map +1 -1
  36. package/dist/controllers/server.d.ts +111 -14
  37. package/dist/controllers/server.js +251 -42
  38. package/dist/controllers/server.js.map +1 -1
  39. package/dist/core/__tests__/health.test.d.ts +1 -0
  40. package/dist/core/__tests__/inMemoryNonceManager.test.d.ts +1 -0
  41. package/dist/core/__tests__/nonceManager.test.d.ts +1 -0
  42. package/dist/core/__tests__/pollingManager.test.d.ts +4 -0
  43. package/dist/core/health.cjs +289 -0
  44. package/dist/core/health.cjs.map +1 -0
  45. package/dist/core/health.d.ts +143 -0
  46. package/dist/core/health.js +265 -0
  47. package/dist/core/health.js.map +1 -0
  48. package/dist/core/inMemoryNonceManager.cjs +138 -0
  49. package/dist/core/inMemoryNonceManager.cjs.map +1 -0
  50. package/dist/core/inMemoryNonceManager.d.ts +69 -0
  51. package/dist/core/inMemoryNonceManager.js +114 -0
  52. package/dist/core/inMemoryNonceManager.js.map +1 -0
  53. package/dist/core/nonceManager.cjs +304 -0
  54. package/dist/core/nonceManager.cjs.map +1 -0
  55. package/dist/core/nonceManager.d.ts +116 -0
  56. package/dist/core/nonceManager.js +280 -0
  57. package/dist/core/nonceManager.js.map +1 -0
  58. package/dist/core/pollingManager.cjs +292 -0
  59. package/dist/core/pollingManager.cjs.map +1 -0
  60. package/dist/core/pollingManager.d.ts +120 -0
  61. package/dist/core/pollingManager.js +268 -0
  62. package/dist/core/pollingManager.js.map +1 -0
  63. package/dist/core.cjs +55 -1
  64. package/dist/core.cjs.map +1 -1
  65. package/dist/core.d.ts +54 -3
  66. package/dist/core.js +55 -1
  67. package/dist/core.js.map +1 -1
  68. package/dist/crypto/ecies/base.cjs +16 -3
  69. package/dist/crypto/ecies/base.cjs.map +1 -1
  70. package/dist/crypto/ecies/base.js +16 -3
  71. package/dist/crypto/ecies/base.js.map +1 -1
  72. package/dist/errors.cjs +29 -0
  73. package/dist/errors.cjs.map +1 -1
  74. package/dist/errors.d.ts +64 -0
  75. package/dist/errors.js +28 -0
  76. package/dist/errors.js.map +1 -1
  77. package/dist/generated/abi/ComputeInstructionRegistryImplementation.cjs.map +1 -1
  78. package/dist/generated/abi/ComputeInstructionRegistryImplementation.js.map +1 -1
  79. package/dist/generated/abi/DLPPerformanceImplementation.cjs +42 -0
  80. package/dist/generated/abi/DLPPerformanceImplementation.cjs.map +1 -1
  81. package/dist/generated/abi/DLPPerformanceImplementation.d.ts +32 -0
  82. package/dist/generated/abi/DLPPerformanceImplementation.js +42 -0
  83. package/dist/generated/abi/DLPPerformanceImplementation.js.map +1 -1
  84. package/dist/generated/abi/DLPRegistryImplementation.cjs +5 -5
  85. package/dist/generated/abi/DLPRegistryImplementation.cjs.map +1 -1
  86. package/dist/generated/abi/DLPRegistryImplementation.d.ts +4 -4
  87. package/dist/generated/abi/DLPRegistryImplementation.js +5 -5
  88. package/dist/generated/abi/DLPRegistryImplementation.js.map +1 -1
  89. package/dist/generated/abi/DLPRewardDeployerImplementation.cjs +166 -2
  90. package/dist/generated/abi/DLPRewardDeployerImplementation.cjs.map +1 -1
  91. package/dist/generated/abi/DLPRewardDeployerImplementation.d.ts +129 -2
  92. package/dist/generated/abi/DLPRewardDeployerImplementation.js +166 -2
  93. package/dist/generated/abi/DLPRewardDeployerImplementation.js.map +1 -1
  94. package/dist/generated/abi/DataPortabilityGranteesImplementation.cjs +167 -19
  95. package/dist/generated/abi/DataPortabilityGranteesImplementation.cjs.map +1 -1
  96. package/dist/generated/abi/DataPortabilityGranteesImplementation.d.ts +127 -14
  97. package/dist/generated/abi/DataPortabilityGranteesImplementation.js +167 -19
  98. package/dist/generated/abi/DataPortabilityGranteesImplementation.js.map +1 -1
  99. package/dist/generated/abi/DataPortabilityPermissionsImplementation.cjs +0 -19
  100. package/dist/generated/abi/DataPortabilityPermissionsImplementation.cjs.map +1 -1
  101. package/dist/generated/abi/DataPortabilityPermissionsImplementation.d.ts +0 -14
  102. package/dist/generated/abi/DataPortabilityPermissionsImplementation.js +0 -19
  103. package/dist/generated/abi/DataPortabilityPermissionsImplementation.js.map +1 -1
  104. package/dist/generated/abi/DataPortabilityServersImplementation.cjs +0 -19
  105. package/dist/generated/abi/DataPortabilityServersImplementation.cjs.map +1 -1
  106. package/dist/generated/abi/DataPortabilityServersImplementation.d.ts +0 -14
  107. package/dist/generated/abi/DataPortabilityServersImplementation.js +0 -19
  108. package/dist/generated/abi/DataPortabilityServersImplementation.js.map +1 -1
  109. package/dist/generated/abi/DataRegistryImplementation.cjs +0 -13
  110. package/dist/generated/abi/DataRegistryImplementation.cjs.map +1 -1
  111. package/dist/generated/abi/DataRegistryImplementation.d.ts +0 -10
  112. package/dist/generated/abi/DataRegistryImplementation.js +0 -13
  113. package/dist/generated/abi/DataRegistryImplementation.js.map +1 -1
  114. package/dist/generated/abi/SwapHelperImplementation.cjs +0 -43
  115. package/dist/generated/abi/SwapHelperImplementation.cjs.map +1 -1
  116. package/dist/generated/abi/SwapHelperImplementation.d.ts +0 -35
  117. package/dist/generated/abi/SwapHelperImplementation.js +0 -43
  118. package/dist/generated/abi/SwapHelperImplementation.js.map +1 -1
  119. package/dist/generated/abi/VanaEpochImplementation.cjs +195 -0
  120. package/dist/generated/abi/VanaEpochImplementation.cjs.map +1 -1
  121. package/dist/generated/abi/VanaEpochImplementation.d.ts +151 -0
  122. package/dist/generated/abi/VanaEpochImplementation.js +195 -0
  123. package/dist/generated/abi/VanaEpochImplementation.js.map +1 -1
  124. package/dist/generated/abi/VanaPoolEntityImplementation.cjs +22 -65
  125. package/dist/generated/abi/VanaPoolEntityImplementation.cjs.map +1 -1
  126. package/dist/generated/abi/VanaPoolEntityImplementation.d.ts +17 -51
  127. package/dist/generated/abi/VanaPoolEntityImplementation.js +22 -65
  128. package/dist/generated/abi/VanaPoolEntityImplementation.js.map +1 -1
  129. package/dist/generated/abi/VanaPoolStakingImplementation.cjs +113 -1
  130. package/dist/generated/abi/VanaPoolStakingImplementation.cjs.map +1 -1
  131. package/dist/generated/abi/VanaPoolStakingImplementation.d.ts +85 -1
  132. package/dist/generated/abi/VanaPoolStakingImplementation.js +113 -1
  133. package/dist/generated/abi/VanaPoolStakingImplementation.js.map +1 -1
  134. package/dist/generated/abi/index.d.ts +546 -146
  135. package/dist/generated/event-types.cjs.map +1 -1
  136. package/dist/generated/event-types.d.ts +14 -8
  137. package/dist/generated/eventRegistry.cjs +42 -18
  138. package/dist/generated/eventRegistry.cjs.map +1 -1
  139. package/dist/generated/eventRegistry.js +42 -18
  140. package/dist/generated/eventRegistry.js.map +1 -1
  141. package/dist/generated/server/server-exports.cjs +22 -0
  142. package/dist/generated/server/server-exports.cjs.map +1 -1
  143. package/dist/generated/server/server-exports.d.ts +27 -10
  144. package/dist/generated/server/server-exports.js +17 -0
  145. package/dist/generated/server/server-exports.js.map +1 -1
  146. package/dist/generated/server/server.cjs.map +1 -1
  147. package/dist/generated/server/server.d.ts +771 -402
  148. package/dist/generated/subgraph.cjs +797 -32
  149. package/dist/generated/subgraph.cjs.map +1 -1
  150. package/dist/generated/subgraph.d.ts +135 -0
  151. package/dist/generated/subgraph.js +792 -32
  152. package/dist/generated/subgraph.js.map +1 -1
  153. package/dist/index.browser.d.ts +2 -0
  154. package/dist/index.browser.js +10 -0
  155. package/dist/index.browser.js.map +1 -1
  156. package/dist/index.node.cjs +26 -0
  157. package/dist/index.node.cjs.map +1 -1
  158. package/dist/index.node.d.ts +49 -5
  159. package/dist/index.node.js +25 -1
  160. package/dist/index.node.js.map +1 -1
  161. package/dist/lib/__tests__/redisAtomicStore.test.d.ts +1 -0
  162. package/dist/lib/redisAtomicStore.cjs +201 -0
  163. package/dist/lib/redisAtomicStore.cjs.map +1 -0
  164. package/dist/lib/redisAtomicStore.d.ts +120 -0
  165. package/dist/lib/redisAtomicStore.js +177 -0
  166. package/dist/lib/redisAtomicStore.js.map +1 -0
  167. package/dist/server/relayerHandler.cjs +313 -75
  168. package/dist/server/relayerHandler.cjs.map +1 -1
  169. package/dist/server/relayerHandler.d.ts +35 -2
  170. package/dist/server/relayerHandler.js +313 -75
  171. package/dist/server/relayerHandler.js.map +1 -1
  172. package/dist/storage/index.cjs +3 -0
  173. package/dist/storage/index.cjs.map +1 -1
  174. package/dist/storage/index.d.ts +1 -0
  175. package/dist/storage/index.js +2 -0
  176. package/dist/storage/index.js.map +1 -1
  177. package/dist/storage/providers/dropbox.cjs +237 -0
  178. package/dist/storage/providers/dropbox.cjs.map +1 -0
  179. package/dist/storage/providers/dropbox.d.ts +39 -0
  180. package/dist/storage/providers/dropbox.js +215 -0
  181. package/dist/storage/providers/dropbox.js.map +1 -0
  182. package/dist/storage/providers/dropbox.test.d.ts +1 -0
  183. package/dist/tests/data-upload-owner-validation.test.d.ts +1 -0
  184. package/dist/types/atomicStore.cjs +31 -0
  185. package/dist/types/atomicStore.cjs.map +1 -0
  186. package/dist/types/atomicStore.d.ts +236 -0
  187. package/dist/types/atomicStore.js +7 -0
  188. package/dist/types/atomicStore.js.map +1 -0
  189. package/dist/types/config.cjs.map +1 -1
  190. package/dist/types/config.d.ts +32 -0
  191. package/dist/types/config.js.map +1 -1
  192. package/dist/types/controller-context.cjs.map +1 -1
  193. package/dist/types/controller-context.d.ts +4 -1
  194. package/dist/types/data.cjs.map +1 -1
  195. package/dist/types/data.d.ts +7 -4
  196. package/dist/types/generics.cjs.map +1 -1
  197. package/dist/types/generics.d.ts +1 -1
  198. package/dist/types/index.cjs.map +1 -1
  199. package/dist/types/index.d.ts +6 -3
  200. package/dist/types/index.js.map +1 -1
  201. package/dist/types/operationStore.cjs +17 -0
  202. package/dist/types/operationStore.cjs.map +1 -0
  203. package/dist/types/operationStore.d.ts +171 -0
  204. package/dist/types/operationStore.js +1 -0
  205. package/dist/types/operationStore.js.map +1 -0
  206. package/dist/types/operations.cjs +3 -15
  207. package/dist/types/operations.cjs.map +1 -1
  208. package/dist/types/operations.d.ts +17 -42
  209. package/dist/types/operations.js +2 -13
  210. package/dist/types/operations.js.map +1 -1
  211. package/dist/types/options.cjs +17 -0
  212. package/dist/types/options.cjs.map +1 -0
  213. package/dist/types/options.d.ts +308 -0
  214. package/dist/types/options.js +1 -0
  215. package/dist/types/options.js.map +1 -0
  216. package/dist/types/permissions.cjs.map +1 -1
  217. package/dist/types/permissions.d.ts +4 -0
  218. package/dist/types/personal.cjs.map +1 -1
  219. package/dist/types/personal.d.ts +19 -0
  220. package/dist/types/relayer.cjs.map +1 -1
  221. package/dist/types/relayer.d.ts +53 -9
  222. package/dist/types/utils.cjs.map +1 -1
  223. package/dist/types/utils.d.ts +0 -49
  224. package/dist/utils/__tests__/chainQuery.test.d.ts +1 -0
  225. package/dist/utils/__tests__/subgraphConsistency.test.d.ts +4 -0
  226. package/dist/utils/__tests__/subgraphPagination.test.d.ts +4 -0
  227. package/dist/utils/chainQuery.cjs +107 -0
  228. package/dist/utils/chainQuery.cjs.map +1 -0
  229. package/dist/utils/chainQuery.d.ts +31 -0
  230. package/dist/utils/chainQuery.js +82 -0
  231. package/dist/utils/chainQuery.js.map +1 -0
  232. package/dist/utils/grantFiles.cjs +4 -1
  233. package/dist/utils/grantFiles.cjs.map +1 -1
  234. package/dist/utils/grantFiles.js +4 -1
  235. package/dist/utils/grantFiles.js.map +1 -1
  236. package/dist/utils/ipfs.cjs +2 -4
  237. package/dist/utils/ipfs.cjs.map +1 -1
  238. package/dist/utils/ipfs.d.ts +1 -1
  239. package/dist/utils/ipfs.js +2 -4
  240. package/dist/utils/ipfs.js.map +1 -1
  241. package/dist/utils/subgraphConsistency.cjs +184 -0
  242. package/dist/utils/subgraphConsistency.cjs.map +1 -0
  243. package/dist/utils/subgraphConsistency.d.ts +65 -0
  244. package/dist/utils/subgraphConsistency.js +155 -0
  245. package/dist/utils/subgraphConsistency.js.map +1 -0
  246. package/dist/utils/subgraphMetaCache.cjs +101 -0
  247. package/dist/utils/subgraphMetaCache.cjs.map +1 -0
  248. package/dist/utils/subgraphMetaCache.d.ts +56 -0
  249. package/dist/utils/subgraphMetaCache.js +76 -0
  250. package/dist/utils/subgraphMetaCache.js.map +1 -0
  251. package/dist/utils/subgraphPagination.cjs +104 -0
  252. package/dist/utils/subgraphPagination.cjs.map +1 -0
  253. package/dist/utils/subgraphPagination.d.ts +78 -0
  254. package/dist/utils/subgraphPagination.js +78 -0
  255. package/dist/utils/subgraphPagination.js.map +1 -0
  256. package/package.json +3 -1
@@ -33,6 +33,7 @@ __export(permissions_exports, {
33
33
  module.exports = __toCommonJS(permissions_exports);
34
34
  var import_viem = require("viem");
35
35
  var import_multicall = require("../utils/multicall");
36
+ var import_pollingManager = require("../core/pollingManager");
36
37
  var import_errors = require("../errors");
37
38
  var import_addresses = require("../config/addresses");
38
39
  var import_abi = require("../generated/abi");
@@ -80,10 +81,14 @@ class PermissionsController extends import_base.BaseController {
80
81
  * await vana.permissions.revoke({ permissionId: result.permissionId });
81
82
  * ```
82
83
  */
83
- async grant(params) {
84
+ async grant(params, options) {
84
85
  this.assertWallet();
85
86
  const { typedData, signature } = await this.createAndSign(params);
86
- const result = await this.submitSignedGrantWithEvents(typedData, signature);
87
+ const result = await this.submitSignedGrantWithEvents(
88
+ typedData,
89
+ signature,
90
+ options
91
+ );
87
92
  return result;
88
93
  }
89
94
  /**
@@ -111,10 +116,10 @@ class PermissionsController extends import_base.BaseController {
111
116
  * console.log(`Permission ID: ${eventData.permissionId}`);
112
117
  * ```
113
118
  */
114
- async submitPermissionGrant(params) {
119
+ async submitPermissionGrant(params, options) {
115
120
  this.assertWallet();
116
121
  const { typedData, signature } = await this.createAndSign(params);
117
- return await this.submitSignedGrant(typedData, signature);
122
+ return await this.submitSignedGrant(typedData, signature, options);
118
123
  }
119
124
  /**
120
125
  * Prepares a permission grant with preview before signing.
@@ -141,7 +146,7 @@ class PermissionsController extends import_base.BaseController {
141
146
  * const transactionHash = await confirm();
142
147
  * ```
143
148
  */
144
- async prepareGrant(params) {
149
+ async prepareGrant(params, options) {
145
150
  this.assertWallet();
146
151
  try {
147
152
  const grantFile = (0, import_grantFiles.createGrantFile)(params);
@@ -149,7 +154,11 @@ class PermissionsController extends import_base.BaseController {
149
154
  return {
150
155
  preview: grantFile,
151
156
  confirm: async () => {
152
- return await this.confirmGrantInternalWithEvents(params, grantFile);
157
+ return await this.confirmGrantInternalWithEvents(
158
+ params,
159
+ grantFile,
160
+ options
161
+ );
153
162
  }
154
163
  };
155
164
  } catch (error) {
@@ -181,7 +190,7 @@ class PermissionsController extends import_base.BaseController {
181
190
  * @throws {NetworkError} When IPFS upload fails
182
191
  * @throws {SignatureError} When user rejects the signature
183
192
  */
184
- async confirmGrantInternal(params, grantFile) {
193
+ async confirmGrantInternal(params, grantFile, options) {
185
194
  try {
186
195
  let { grantUrl } = params;
187
196
  console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
@@ -206,7 +215,7 @@ class PermissionsController extends import_base.BaseController {
206
215
  if (response.type === "error") {
207
216
  throw new Error(response.error);
208
217
  }
209
- if (response.type === "direct" && typeof response.result === "object" && "url" in response.result) {
218
+ if (response.type === "direct" && typeof response.result === "object" && response.result !== null && "url" in response.result) {
210
219
  grantUrl = response.result.url;
211
220
  } else {
212
221
  throw new Error("Invalid response from relayer for grant storage");
@@ -242,7 +251,7 @@ class PermissionsController extends import_base.BaseController {
242
251
  nonce
243
252
  });
244
253
  const signature = await this.signTypedData(typedData);
245
- return await this.submitSignedGrant(typedData, signature);
254
+ return await this.submitSignedGrant(typedData, signature, options);
246
255
  } catch (error) {
247
256
  if (error instanceof Error) {
248
257
  if (error instanceof import_errors.RelayerError || error instanceof import_errors.UserRejectedRequestError || error instanceof import_errors.SerializationError || error instanceof import_errors.SignatureError || error instanceof import_errors.NetworkError || error instanceof import_errors.NonceError) {
@@ -314,7 +323,7 @@ class PermissionsController extends import_base.BaseController {
314
323
  if (response.type === "error") {
315
324
  throw new Error(response.error);
316
325
  }
317
- if (response.type === "direct" && typeof response.result === "object" && "url" in response.result) {
326
+ if (response.type === "direct" && typeof response.result === "object" && response.result !== null && "url" in response.result) {
318
327
  grantUrl = response.result.url;
319
328
  } else {
320
329
  throw new Error("Invalid response from relayer for grant storage");
@@ -387,7 +396,7 @@ class PermissionsController extends import_base.BaseController {
387
396
  * );
388
397
  * ```
389
398
  */
390
- async submitSignedGrant(typedData, signature) {
399
+ async submitSignedGrant(typedData, signature, options) {
391
400
  try {
392
401
  console.debug(
393
402
  "\u{1F50D} Debug - submitSignedGrant called with typed data:",
@@ -405,26 +414,41 @@ class PermissionsController extends import_base.BaseController {
405
414
  signature,
406
415
  expectedUserAddress: this.context.userAddress
407
416
  });
408
- let hash;
409
- if (response.type === "signed") {
410
- hash = response.hash;
411
- } else if (response.type === "error") {
417
+ if (response.type === "error") {
412
418
  throw new Error(`Relayer error: ${response.error}`);
419
+ }
420
+ let finalHash;
421
+ if (response.type === "submitted") {
422
+ finalHash = response.hash;
423
+ } else if (response.type === "pending") {
424
+ const pollResult = await this.pollRelayerForConfirmation(
425
+ response.operationId,
426
+ options
427
+ );
428
+ finalHash = pollResult.hash;
429
+ } else if (response.type === "confirmed") {
430
+ finalHash = response.hash;
431
+ } else if (response.type === "signed") {
432
+ finalHash = response.hash;
413
433
  } else {
414
434
  throw new Error(
415
- "Invalid response from relayer: expected signed transaction"
435
+ "Invalid response from relayer: unexpected response type"
416
436
  );
417
437
  }
418
438
  const account = this.context.walletClient?.account ?? this.context.userAddress;
419
439
  const { tx } = await import("../utils/transactionHelpers");
420
440
  return tx({
421
- hash,
441
+ hash: finalHash,
422
442
  from: typeof account === "string" ? account : account.address,
423
443
  contract: "DataPortabilityPermissions",
424
444
  fn: "addPermission"
425
445
  });
426
446
  } else {
427
- return await this.submitDirectTransaction(typedData, signature);
447
+ return await this.submitDirectTransaction(
448
+ typedData,
449
+ signature,
450
+ options
451
+ );
428
452
  }
429
453
  } catch (error) {
430
454
  if (error instanceof import_errors.RelayerError || error instanceof import_errors.NetworkError || error instanceof import_errors.UserRejectedRequestError || error instanceof import_errors.SignatureError || error instanceof import_errors.NonceError) {
@@ -457,7 +481,7 @@ class PermissionsController extends import_base.BaseController {
457
481
  * const result = await txHandle.waitForEvents();
458
482
  * ```
459
483
  */
460
- async submitSignedTrustServer(typedData, signature) {
484
+ async submitSignedTrustServer(typedData, signature, options) {
461
485
  try {
462
486
  const trustServerInput = {
463
487
  nonce: BigInt(typedData.message.nonce),
@@ -465,7 +489,8 @@ class PermissionsController extends import_base.BaseController {
465
489
  };
466
490
  const hash = await this.submitTrustServerTransaction(
467
491
  trustServerInput,
468
- signature
492
+ signature,
493
+ options
469
494
  );
470
495
  const account = this.context.userAddress;
471
496
  const { tx } = await import("../utils/transactionHelpers");
@@ -520,7 +545,7 @@ class PermissionsController extends import_base.BaseController {
520
545
  * const result = await txHandle.waitForEvents();
521
546
  * ```
522
547
  */
523
- async submitSignedAddAndTrustServer(typedData, signature) {
548
+ async submitSignedAddAndTrustServer(typedData, signature, options) {
524
549
  try {
525
550
  const addAndTrustServerInput = {
526
551
  nonce: BigInt(typedData.message.nonce),
@@ -530,7 +555,8 @@ class PermissionsController extends import_base.BaseController {
530
555
  };
531
556
  const hash = await this.submitAddAndTrustServerTransaction(
532
557
  addAndTrustServerInput,
533
- signature
558
+ signature,
559
+ options
534
560
  );
535
561
  const account = this.context.walletClient?.account ?? this.context.userAddress;
536
562
  const { tx } = await import("../utils/transactionHelpers");
@@ -558,8 +584,12 @@ class PermissionsController extends import_base.BaseController {
558
584
  * @param signature - The user's signature authorizing the transaction
559
585
  * @returns Promise resolving to PermissionGrantResult with parsed events
560
586
  */
561
- async submitSignedGrantWithEvents(typedData, signature) {
562
- const txResult = await this.submitSignedGrant(typedData, signature);
587
+ async submitSignedGrantWithEvents(typedData, signature, options) {
588
+ const txResult = await this.submitSignedGrant(
589
+ typedData,
590
+ signature,
591
+ options
592
+ );
563
593
  if (!this.context.waitForTransactionEvents) {
564
594
  throw new import_errors.BlockchainError("waitForTransactionEvents not configured");
565
595
  }
@@ -591,8 +621,12 @@ class PermissionsController extends import_base.BaseController {
591
621
  * @param grantFile - The pre-created grant file object
592
622
  * @returns Promise resolving to PermissionGrantResult with parsed events
593
623
  */
594
- async confirmGrantInternalWithEvents(params, grantFile) {
595
- const txResult = await this.confirmGrantInternal(params, grantFile);
624
+ async confirmGrantInternalWithEvents(params, grantFile, options) {
625
+ const txResult = await this.confirmGrantInternal(
626
+ params,
627
+ grantFile,
628
+ options
629
+ );
596
630
  if (!this.context.waitForTransactionEvents) {
597
631
  throw new import_errors.BlockchainError("waitForTransactionEvents not configured");
598
632
  }
@@ -616,6 +650,27 @@ class PermissionsController extends import_base.BaseController {
616
650
  fileIds: event.fileIds
617
651
  };
618
652
  }
653
+ /**
654
+ * Polls the relayer for confirmation of a pending operation.
655
+ *
656
+ * @param operationId - The operation ID to poll
657
+ * @param options - Polling configuration including status updates and cancellation
658
+ * @returns Promise resolving to the confirmed hash and receipt
659
+ * @throws {TransactionPendingError} When the operation times out
660
+ * @throws {Error} When the operation fails or is cancelled
661
+ * @internal
662
+ */
663
+ async pollRelayerForConfirmation(operationId, options) {
664
+ if (!this.context.relayer) {
665
+ throw new Error("Relayer not configured for polling");
666
+ }
667
+ const pollingManager = new import_pollingManager.PollingManager(this.context.relayer);
668
+ return await pollingManager.startPolling(operationId, {
669
+ signal: options?.signal,
670
+ onStatusUpdate: options?.onStatusUpdate,
671
+ ...options?.pollingOptions
672
+ });
673
+ }
619
674
  /**
620
675
  * Submits an already-signed permission revoke transaction to the blockchain.
621
676
  *
@@ -637,7 +692,7 @@ class PermissionsController extends import_base.BaseController {
637
692
  * const result = await txHandle.waitForEvents();
638
693
  * ```
639
694
  */
640
- async submitSignedRevoke(typedData, signature) {
695
+ async submitSignedRevoke(typedData, signature, options) {
641
696
  try {
642
697
  let hash;
643
698
  if (this.context.relayer) {
@@ -648,19 +703,31 @@ class PermissionsController extends import_base.BaseController {
648
703
  signature,
649
704
  expectedUserAddress: this.context.userAddress
650
705
  });
651
- if (response.type === "signed") {
652
- hash = response.hash;
653
- } else if (response.type === "error") {
706
+ if (response.type === "error") {
654
707
  throw new Error(`Relayer error: ${response.error}`);
708
+ }
709
+ if (response.type === "submitted") {
710
+ hash = response.hash;
711
+ } else if (response.type === "pending") {
712
+ const pollResult = await this.pollRelayerForConfirmation(
713
+ response.operationId,
714
+ options
715
+ );
716
+ hash = pollResult.hash;
717
+ } else if (response.type === "confirmed") {
718
+ hash = response.hash;
719
+ } else if (response.type === "signed") {
720
+ hash = response.hash;
655
721
  } else {
656
722
  throw new Error(
657
- "Invalid response from relayer: expected signed transaction"
723
+ "Invalid response from relayer: unexpected response type"
658
724
  );
659
725
  }
660
726
  } else {
661
727
  hash = await this.submitDirectRevokeTransaction(
662
728
  typedData,
663
- signature
729
+ signature,
730
+ options
664
731
  );
665
732
  }
666
733
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -702,7 +769,7 @@ class PermissionsController extends import_base.BaseController {
702
769
  * const result = await txHandle.waitForEvents();
703
770
  * ```
704
771
  */
705
- async submitSignedUntrustServer(typedData, signature) {
772
+ async submitSignedUntrustServer(typedData, signature, options) {
706
773
  try {
707
774
  let hash;
708
775
  if (this.context.relayer) {
@@ -713,7 +780,9 @@ class PermissionsController extends import_base.BaseController {
713
780
  signature,
714
781
  expectedUserAddress: this.context.userAddress
715
782
  });
716
- if (response.type === "signed") {
783
+ if (response.type === "submitted") {
784
+ hash = response.hash;
785
+ } else if (response.type === "signed") {
717
786
  hash = response.hash;
718
787
  } else if (response.type === "error") {
719
788
  throw new Error(`Relayer error: ${response.error}`);
@@ -725,7 +794,8 @@ class PermissionsController extends import_base.BaseController {
725
794
  } else {
726
795
  hash = await this.submitSignedUntrustTransaction(
727
796
  typedData,
728
- signature
797
+ signature,
798
+ options
729
799
  );
730
800
  }
731
801
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -758,7 +828,7 @@ class PermissionsController extends import_base.BaseController {
758
828
  * @returns Promise resolving to the transaction hash
759
829
  * @throws {BlockchainError} When contract submission fails
760
830
  */
761
- async submitDirectTransaction(typedData, signature) {
831
+ async submitDirectTransaction(typedData, signature, options) {
762
832
  this.assertWallet();
763
833
  const chainId = await this.context.publicClient.getChainId();
764
834
  const DataPortabilityPermissionsAddress = (0, import_addresses.getContractAddress)(
@@ -790,7 +860,8 @@ class PermissionsController extends import_base.BaseController {
790
860
  functionName: "addPermission",
791
861
  args: [permissionInput, formattedSignature],
792
862
  account,
793
- chain: this.context.walletClient?.chain ?? null
863
+ chain: this.context.walletClient?.chain ?? null,
864
+ ...this.spreadTransactionOptions(options)
794
865
  });
795
866
  const { tx } = await import("../utils/transactionHelpers");
796
867
  return tx({
@@ -889,7 +960,7 @@ class PermissionsController extends import_base.BaseController {
889
960
  args: [params.permissionId],
890
961
  account,
891
962
  chain: this.context.walletClient?.chain ?? null,
892
- ...options?.gasLimit && { gas: options.gasLimit },
963
+ ...options?.gas && { gas: options.gas },
893
964
  ...options?.nonce && { nonce: options.nonce },
894
965
  // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
895
966
  ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
@@ -946,7 +1017,7 @@ class PermissionsController extends import_base.BaseController {
946
1017
  * console.log(`Permission ${result.permissionId} revoked`);
947
1018
  * ```
948
1019
  */
949
- async submitRevokeWithSignature(params) {
1020
+ async submitRevokeWithSignature(params, options) {
950
1021
  this.assertWallet();
951
1022
  try {
952
1023
  if (!this.context.walletClient?.chain?.id) {
@@ -978,7 +1049,9 @@ class PermissionsController extends import_base.BaseController {
978
1049
  signature,
979
1050
  expectedUserAddress: this.context.userAddress
980
1051
  });
981
- if (response.type === "signed") {
1052
+ if (response.type === "submitted") {
1053
+ hash = response.hash;
1054
+ } else if (response.type === "signed") {
982
1055
  hash = response.hash;
983
1056
  } else if (response.type === "error") {
984
1057
  throw new Error(`Relayer error: ${response.error}`);
@@ -990,7 +1063,8 @@ class PermissionsController extends import_base.BaseController {
990
1063
  } else {
991
1064
  hash = await this.submitDirectRevokeTransaction(
992
1065
  typedData,
993
- signature
1066
+ signature,
1067
+ options
994
1068
  );
995
1069
  }
996
1070
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -1316,7 +1390,9 @@ class PermissionsController extends import_base.BaseController {
1316
1390
  * ```
1317
1391
  */
1318
1392
  async getUserPermissionGrantsOnChain(options = {}) {
1319
- const { limit = 50, subgraphUrl } = options;
1393
+ const { limit = 50, fetchAll = false, subgraphUrl } = options;
1394
+ const pageSize = fetchAll ? 100 : limit;
1395
+ const maxResults = fetchAll ? 1e4 : limit;
1320
1396
  try {
1321
1397
  const userAddress = this.context.userAddress;
1322
1398
  const graphqlEndpoint = subgraphUrl ?? this.context.subgraphUrl;
@@ -1326,10 +1402,10 @@ class PermissionsController extends import_base.BaseController {
1326
1402
  );
1327
1403
  }
1328
1404
  const query = `
1329
- query GetUserPermissions($userId: ID!) {
1405
+ query GetUserPermissions($userId: ID!, $first: Int!, $skip: Int!) {
1330
1406
  user(id: $userId) {
1331
1407
  id
1332
- permissions {
1408
+ permissions(first: $first, skip: $skip, orderBy: addedAtBlock, orderDirection: desc) {
1333
1409
  id
1334
1410
  grant
1335
1411
  nonce
@@ -1347,34 +1423,82 @@ class PermissionsController extends import_base.BaseController {
1347
1423
  }
1348
1424
  }
1349
1425
  `;
1350
- const response = await fetch(graphqlEndpoint, {
1351
- method: "POST",
1352
- headers: {
1353
- "Content-Type": "application/json"
1354
- },
1355
- body: JSON.stringify({
1356
- query,
1357
- variables: {
1358
- userId: userAddress.toLowerCase()
1426
+ const allPermissions = [];
1427
+ let currentOffset = 0;
1428
+ if (!fetchAll) {
1429
+ const response = await fetch(graphqlEndpoint, {
1430
+ method: "POST",
1431
+ headers: {
1432
+ "Content-Type": "application/json"
1433
+ },
1434
+ body: JSON.stringify({
1435
+ query,
1436
+ variables: {
1437
+ userId: userAddress.toLowerCase(),
1438
+ first: limit,
1439
+ skip: 0
1440
+ }
1441
+ })
1442
+ });
1443
+ if (!response.ok) {
1444
+ throw new import_errors.BlockchainError(
1445
+ `Subgraph request failed: ${response.status} ${response.statusText}`
1446
+ );
1447
+ }
1448
+ const result = await response.json();
1449
+ if (result.errors) {
1450
+ throw new import_errors.BlockchainError(
1451
+ `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
1452
+ );
1453
+ }
1454
+ const userData = result.data?.user;
1455
+ if (!userData?.permissions?.length) {
1456
+ return [];
1457
+ }
1458
+ allPermissions.push(...userData.permissions);
1459
+ } else {
1460
+ while (allPermissions.length < maxResults) {
1461
+ const currentLimit = Math.min(
1462
+ pageSize,
1463
+ maxResults - allPermissions.length
1464
+ );
1465
+ const response = await fetch(graphqlEndpoint, {
1466
+ method: "POST",
1467
+ headers: {
1468
+ "Content-Type": "application/json"
1469
+ },
1470
+ body: JSON.stringify({
1471
+ query,
1472
+ variables: {
1473
+ userId: userAddress.toLowerCase(),
1474
+ first: currentLimit,
1475
+ skip: currentOffset
1476
+ }
1477
+ })
1478
+ });
1479
+ if (!response.ok) {
1480
+ throw new import_errors.BlockchainError(
1481
+ `Subgraph request failed: ${response.status} ${response.statusText}`
1482
+ );
1359
1483
  }
1360
- })
1361
- });
1362
- if (!response.ok) {
1363
- throw new import_errors.BlockchainError(
1364
- `Subgraph request failed: ${response.status} ${response.statusText}`
1365
- );
1366
- }
1367
- const result = await response.json();
1368
- if (result.errors) {
1369
- throw new import_errors.BlockchainError(
1370
- `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
1371
- );
1372
- }
1373
- const userData = result.data?.user;
1374
- if (!userData?.permissions?.length) {
1375
- return [];
1484
+ const result = await response.json();
1485
+ if (result.errors) {
1486
+ throw new import_errors.BlockchainError(
1487
+ `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
1488
+ );
1489
+ }
1490
+ const userData = result.data?.user;
1491
+ if (!userData?.permissions?.length) {
1492
+ break;
1493
+ }
1494
+ allPermissions.push(...userData.permissions);
1495
+ if (userData.permissions.length < currentLimit) {
1496
+ break;
1497
+ }
1498
+ currentOffset += userData.permissions.length;
1499
+ }
1376
1500
  }
1377
- const onChainGrants = userData.permissions.slice(0, limit).map(
1501
+ const onChainGrants = allPermissions.map(
1378
1502
  (permission) => ({
1379
1503
  id: BigInt(permission.id),
1380
1504
  grantUrl: permission.grant,
@@ -1555,7 +1679,7 @@ class PermissionsController extends import_base.BaseController {
1555
1679
  * @param params - Parameters for adding and trusting the server
1556
1680
  * @returns Promise resolving to TransactionResult with ServerTrustResult event data
1557
1681
  */
1558
- async submitAddAndTrustServerWithSignature(params) {
1682
+ async submitAddAndTrustServerWithSignature(params, options) {
1559
1683
  this.assertWallet();
1560
1684
  try {
1561
1685
  const nonce = await this.getServersUserNonce();
@@ -1591,7 +1715,9 @@ class PermissionsController extends import_base.BaseController {
1591
1715
  if (response.type === "error") {
1592
1716
  throw new import_errors.RelayerError(response.error);
1593
1717
  }
1594
- if (response.type === "signed") {
1718
+ if (response.type === "submitted") {
1719
+ hash = response.hash;
1720
+ } else if (response.type === "signed") {
1595
1721
  hash = response.hash;
1596
1722
  } else {
1597
1723
  throw new Error("Unexpected response type from relayer");
@@ -1599,7 +1725,8 @@ class PermissionsController extends import_base.BaseController {
1599
1725
  } else {
1600
1726
  hash = await this.submitAddAndTrustServerTransaction(
1601
1727
  addAndTrustServerInput,
1602
- signature
1728
+ signature,
1729
+ options
1603
1730
  );
1604
1731
  }
1605
1732
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -1638,7 +1765,7 @@ class PermissionsController extends import_base.BaseController {
1638
1765
  * @throws {ServerUrlMismatchError} When server URL doesn't match existing registration
1639
1766
  * @throws {BlockchainError} When trust operation fails for any other reason
1640
1767
  */
1641
- async submitTrustServerWithSignature(params) {
1768
+ async submitTrustServerWithSignature(params, options) {
1642
1769
  this.assertWallet();
1643
1770
  try {
1644
1771
  const nonce = await this.getServersUserNonce();
@@ -1660,7 +1787,9 @@ class PermissionsController extends import_base.BaseController {
1660
1787
  if (response.type === "error") {
1661
1788
  throw new import_errors.RelayerError(response.error);
1662
1789
  }
1663
- if (response.type === "signed") {
1790
+ if (response.type === "submitted") {
1791
+ hash = response.hash;
1792
+ } else if (response.type === "signed") {
1664
1793
  hash = response.hash;
1665
1794
  } else {
1666
1795
  throw new Error("Unexpected response type from relayer");
@@ -1668,7 +1797,8 @@ class PermissionsController extends import_base.BaseController {
1668
1797
  } else {
1669
1798
  hash = await this.submitTrustServerTransaction(
1670
1799
  trustServerInput,
1671
- signature
1800
+ signature,
1801
+ options
1672
1802
  );
1673
1803
  }
1674
1804
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -1726,7 +1856,7 @@ class PermissionsController extends import_base.BaseController {
1726
1856
  args: [BigInt(params.serverId)],
1727
1857
  account,
1728
1858
  chain: this.context.walletClient?.chain ?? null,
1729
- ...options?.gasLimit && { gas: options.gasLimit },
1859
+ ...options?.gas && { gas: options.gas },
1730
1860
  ...options?.nonce && { nonce: options.nonce },
1731
1861
  // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
1732
1862
  ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
@@ -1830,7 +1960,9 @@ class PermissionsController extends import_base.BaseController {
1830
1960
  if (response.type === "error") {
1831
1961
  throw new import_errors.RelayerError(response.error);
1832
1962
  }
1833
- if (response.type === "signed") {
1963
+ if (response.type === "submitted") {
1964
+ hash = response.hash;
1965
+ } else if (response.type === "signed") {
1834
1966
  hash = response.hash;
1835
1967
  } else {
1836
1968
  throw new Error("Unexpected response type from relayer");
@@ -2276,7 +2408,7 @@ class PermissionsController extends import_base.BaseController {
2276
2408
  * @param signature - The cryptographic signature for the transaction
2277
2409
  * @returns Promise resolving to the transaction hash
2278
2410
  */
2279
- async submitAddAndTrustServerTransaction(addAndTrustServerInput, signature) {
2411
+ async submitAddAndTrustServerTransaction(addAndTrustServerInput, signature, options) {
2280
2412
  this.assertWallet();
2281
2413
  const chainId = await this.context.walletClient.getChainId();
2282
2414
  const DataPortabilityServersAddress = (0, import_addresses.getContractAddress)(
@@ -2310,7 +2442,16 @@ class PermissionsController extends import_base.BaseController {
2310
2442
  formattedSignature
2311
2443
  ],
2312
2444
  account: this.context.walletClient?.account ?? this.context.userAddress,
2313
- chain: this.context.walletClient?.chain ?? null
2445
+ chain: this.context.walletClient?.chain ?? null,
2446
+ ...options && {
2447
+ gas: options.gas,
2448
+ nonce: options.nonce,
2449
+ // Use EIP-1559 gas pricing if available, otherwise legacy
2450
+ ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2451
+ maxFeePerGas: options.maxFeePerGas,
2452
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
2453
+ } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2454
+ }
2314
2455
  });
2315
2456
  return txHash;
2316
2457
  }
@@ -2321,7 +2462,7 @@ class PermissionsController extends import_base.BaseController {
2321
2462
  * @param signature - The cryptographic signature for the transaction
2322
2463
  * @returns Promise resolving to the transaction hash
2323
2464
  */
2324
- async submitTrustServerTransaction(trustServerInput, signature) {
2465
+ async submitTrustServerTransaction(trustServerInput, signature, options) {
2325
2466
  this.assertWallet();
2326
2467
  const chainId = await this.context.walletClient.getChainId();
2327
2468
  const DataPortabilityServersAddress = (0, import_addresses.getContractAddress)(
@@ -2342,7 +2483,8 @@ class PermissionsController extends import_base.BaseController {
2342
2483
  formattedSignature
2343
2484
  ],
2344
2485
  account: this.context.walletClient?.account ?? this.context.userAddress,
2345
- chain: this.context.walletClient?.chain ?? null
2486
+ chain: this.context.walletClient?.chain ?? null,
2487
+ ...this.spreadTransactionOptions(options)
2346
2488
  });
2347
2489
  return txHash;
2348
2490
  }
@@ -2353,7 +2495,7 @@ class PermissionsController extends import_base.BaseController {
2353
2495
  * @param signature - The cryptographic signature authorizing the revoke
2354
2496
  * @returns Promise resolving to the transaction hash
2355
2497
  */
2356
- async submitDirectRevokeTransaction(typedData, signature) {
2498
+ async submitDirectRevokeTransaction(typedData, signature, options) {
2357
2499
  this.assertWallet();
2358
2500
  const chainId = await this.context.walletClient.getChainId();
2359
2501
  const DataPortabilityPermissionsAddress = (0, import_addresses.getContractAddress)(
@@ -2368,7 +2510,16 @@ class PermissionsController extends import_base.BaseController {
2368
2510
  functionName: "revokePermissionWithSignature",
2369
2511
  args: [typedData.message, formattedSignature],
2370
2512
  account: this.context.walletClient?.account ?? this.context.userAddress,
2371
- chain: this.context.walletClient?.chain ?? null
2513
+ chain: this.context.walletClient?.chain ?? null,
2514
+ ...options && {
2515
+ gas: options.gas,
2516
+ nonce: options.nonce,
2517
+ // Use EIP-1559 gas pricing if available, otherwise legacy
2518
+ ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2519
+ maxFeePerGas: options.maxFeePerGas,
2520
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
2521
+ } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2522
+ }
2372
2523
  });
2373
2524
  return txHash;
2374
2525
  }
@@ -2379,7 +2530,7 @@ class PermissionsController extends import_base.BaseController {
2379
2530
  * @param signature - The cryptographic signature authorizing the untrust
2380
2531
  * @returns Promise resolving to the transaction hash
2381
2532
  */
2382
- async submitSignedUntrustTransaction(typedData, signature) {
2533
+ async submitSignedUntrustTransaction(typedData, signature, options) {
2383
2534
  this.assertWallet();
2384
2535
  const chainId = await this.context.walletClient.getChainId();
2385
2536
  const DataPortabilityServersAddress = (0, import_addresses.getContractAddress)(
@@ -2398,7 +2549,16 @@ class PermissionsController extends import_base.BaseController {
2398
2549
  functionName: "untrustServerWithSignature",
2399
2550
  args: [contractMessage, formattedSignature],
2400
2551
  account: this.context.walletClient?.account ?? this.context.userAddress,
2401
- chain: this.context.walletClient?.chain ?? null
2552
+ chain: this.context.walletClient?.chain ?? null,
2553
+ ...options && {
2554
+ gas: options.gas,
2555
+ nonce: options.nonce,
2556
+ // Use EIP-1559 gas pricing if available, otherwise legacy
2557
+ ...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
2558
+ maxFeePerGas: options.maxFeePerGas,
2559
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
2560
+ } : options.gasPrice ? { gasPrice: options.gasPrice } : {}
2561
+ }
2402
2562
  });
2403
2563
  return txHash;
2404
2564
  }
@@ -2411,6 +2571,9 @@ class PermissionsController extends import_base.BaseController {
2411
2571
  * A grantee is an entity (like an application) that can receive data permissions
2412
2572
  * from users. Once registered, users can grant the grantee access to their data.
2413
2573
  *
2574
+ * This method supports gasless transactions via relayer when configured.
2575
+ * If no relayer is available, it falls back to direct wallet transactions.
2576
+ *
2414
2577
  * @param params - Parameters for registering the grantee
2415
2578
  * @param params.owner - The Ethereum address that will own this grantee registration
2416
2579
  * @param params.granteeAddress - The Ethereum address of the grantee (application)
@@ -2419,7 +2582,7 @@ class PermissionsController extends import_base.BaseController {
2419
2582
  * @returns Promise resolving to the transaction hash
2420
2583
  * @throws {BlockchainError} When the grantee registration transaction fails
2421
2584
  * @throws {UserRejectedRequestError} When user rejects the transaction
2422
- * @throws {ContractError} When grantee is already registered
2585
+ * @throws {RelayerError} When gasless transaction submission fails
2423
2586
  *
2424
2587
  * @example
2425
2588
  * ```typescript
@@ -2432,44 +2595,87 @@ class PermissionsController extends import_base.BaseController {
2432
2595
  * ```
2433
2596
  */
2434
2597
  async submitRegisterGrantee(params, options) {
2435
- this.assertWallet();
2436
- const chainId = await this.context.walletClient.getChainId();
2437
- const DataPortabilityGranteesAddress = (0, import_addresses.getContractAddress)(
2438
- chainId,
2439
- "DataPortabilityGrantees"
2440
- );
2441
- const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
2442
- const ownerAddress = (0, import_viem.getAddress)(params.owner);
2443
- const granteeAddress = (0, import_viem.getAddress)(params.granteeAddress);
2444
- const account = this.context.walletClient?.account ?? this.context.userAddress;
2445
- const txHash = await this.context.walletClient.writeContract({
2446
- address: DataPortabilityGranteesAddress,
2447
- abi: DataPortabilityGranteesAbi,
2448
- functionName: "registerGrantee",
2449
- args: [ownerAddress, granteeAddress, params.publicKey],
2450
- account,
2451
- chain: this.context.walletClient?.chain ?? null,
2452
- ...options?.gasLimit && { gas: options.gasLimit },
2453
- ...options?.nonce && { nonce: options.nonce },
2454
- // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
2455
- ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
2456
- ...options.maxFeePerGas && { maxFeePerGas: options.maxFeePerGas },
2457
- ...options.maxPriorityFeePerGas && {
2458
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
2598
+ try {
2599
+ let hash;
2600
+ if (this.context.relayer) {
2601
+ const request = {
2602
+ type: "direct",
2603
+ operation: "submitRegisterGrantee",
2604
+ params: {
2605
+ owner: params.owner,
2606
+ granteeAddress: params.granteeAddress,
2607
+ publicKey: params.publicKey
2608
+ }
2609
+ };
2610
+ const response = await this.context.relayer(request);
2611
+ if (response.type === "error") {
2612
+ throw new import_errors.RelayerError(response.error);
2459
2613
  }
2460
- } : options?.gasPrice && { gasPrice: options.gasPrice }
2461
- });
2462
- const { tx } = await import("../utils/transactionHelpers");
2463
- return tx({
2464
- hash: txHash,
2465
- from: typeof account === "string" ? account : account.address,
2466
- contract: "DataPortabilityGrantees",
2467
- fn: "registerGrantee"
2468
- });
2614
+ if (response.type === "submitted") {
2615
+ hash = response.hash;
2616
+ } else if (response.type === "direct") {
2617
+ const result = response.result;
2618
+ hash = result.transactionHash;
2619
+ } else {
2620
+ throw new Error("Unexpected response type from relayer");
2621
+ }
2622
+ } else {
2623
+ this.assertWallet();
2624
+ const chainId = await this.context.walletClient.getChainId();
2625
+ const DataPortabilityGranteesAddress = (0, import_addresses.getContractAddress)(
2626
+ chainId,
2627
+ "DataPortabilityGrantees"
2628
+ );
2629
+ const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
2630
+ const ownerAddress = (0, import_viem.getAddress)(params.owner);
2631
+ const granteeAddress = (0, import_viem.getAddress)(params.granteeAddress);
2632
+ const account2 = this.context.walletClient?.account ?? this.context.userAddress;
2633
+ hash = await this.context.walletClient.writeContract({
2634
+ address: DataPortabilityGranteesAddress,
2635
+ abi: DataPortabilityGranteesAbi,
2636
+ functionName: "registerGrantee",
2637
+ args: [ownerAddress, granteeAddress, params.publicKey],
2638
+ account: account2,
2639
+ chain: this.context.walletClient?.chain ?? null,
2640
+ ...this.spreadTransactionOptions(options)
2641
+ });
2642
+ }
2643
+ const account = this.context.walletClient?.account ?? this.context.userAddress;
2644
+ const { tx } = await import("../utils/transactionHelpers");
2645
+ return tx({
2646
+ hash,
2647
+ from: typeof account === "string" ? account : account.address,
2648
+ contract: "DataPortabilityGrantees",
2649
+ fn: "registerGrantee"
2650
+ });
2651
+ } catch (error) {
2652
+ if (error instanceof Error) {
2653
+ if (error instanceof import_errors.RelayerError || error instanceof import_errors.UserRejectedRequestError || error instanceof import_errors.SerializationError || error instanceof import_errors.SignatureError || error instanceof import_errors.BlockchainError) {
2654
+ throw error;
2655
+ }
2656
+ if (error.name === "ContractFunctionExecutionError") {
2657
+ throw new import_errors.BlockchainError(
2658
+ `Grantee registration failed: ${error.message}`,
2659
+ error
2660
+ );
2661
+ }
2662
+ if (error.name === "UserRejectedRequestError") {
2663
+ throw new import_errors.UserRejectedRequestError(
2664
+ "User rejected the grantee registration transaction"
2665
+ );
2666
+ }
2667
+ throw new import_errors.BlockchainError(
2668
+ `Failed to register grantee: ${error.message}`,
2669
+ error
2670
+ );
2671
+ }
2672
+ throw new import_errors.BlockchainError(`Failed to register grantee: ${String(error)}`);
2673
+ }
2469
2674
  }
2470
2675
  // TODO: When DataPortabilityGrantees contract adds registerGranteeWithSignature function,
2471
2676
  // implement submitRegisterGranteeWithSignature and submitSignedRegisterGrantee methods
2472
- // to support gasless transactions via relayer
2677
+ // to support EIP-712 signed gasless transactions via relayer.
2678
+ // Current implementation above supports direct gasless transactions (relayer pays gas directly).
2473
2679
  /**
2474
2680
  * Retrieves all registered grantees from the DataPortabilityGrantees contract.
2475
2681
  *
@@ -2517,27 +2723,52 @@ class PermissionsController extends import_base.BaseController {
2517
2723
  const total = Number(totalCount);
2518
2724
  const limit = options.limit ?? 50;
2519
2725
  const offset = options.offset ?? 0;
2520
- const grantees = [];
2521
- const endIndex = Math.min(offset + limit, total);
2522
- for (let i = offset; i < endIndex; i++) {
2523
- try {
2524
- const granteeInfo = await this.context.publicClient.readContract({
2525
- address: DataPortabilityGranteesAddress,
2526
- abi: DataPortabilityGranteesAbi,
2527
- functionName: "grantees",
2528
- args: [BigInt(i + 1)]
2529
- // Grantee IDs are 1-indexed
2530
- });
2531
- grantees.push({
2532
- id: i + 1,
2533
- owner: granteeInfo.owner,
2534
- address: granteeInfo.granteeAddress,
2535
- publicKey: granteeInfo.publicKey,
2536
- permissionIds: granteeInfo.permissionIds.map((id) => Number(id))
2537
- });
2538
- } catch (error) {
2539
- console.warn(`Failed to fetch grantee ${i + 1}:`, error);
2540
- }
2726
+ const includePermissions = options.includePermissions ?? true;
2727
+ const startId = total - offset;
2728
+ const endId = Math.max(startId - limit + 1, 1);
2729
+ const granteeIds = Array.from(
2730
+ { length: startId - endId + 1 },
2731
+ (_, i) => startId - i
2732
+ // Generate IDs in descending order
2733
+ );
2734
+ let grantees;
2735
+ if (includePermissions) {
2736
+ const granteePromises = granteeIds.map(
2737
+ (granteeId) => this.getGranteeById(granteeId)
2738
+ );
2739
+ const granteeResults = await Promise.all(granteePromises);
2740
+ grantees = granteeResults.filter(
2741
+ (grantee) => grantee !== null
2742
+ );
2743
+ } else {
2744
+ const granteeInfoPromises = granteeIds.map(
2745
+ async (granteeId) => {
2746
+ try {
2747
+ const granteeInfo = await this.context.publicClient.readContract({
2748
+ address: DataPortabilityGranteesAddress,
2749
+ abi: DataPortabilityGranteesAbi,
2750
+ functionName: "granteesV2",
2751
+ args: [BigInt(granteeId)]
2752
+ });
2753
+ const grantee = {
2754
+ id: granteeId,
2755
+ owner: granteeInfo.owner,
2756
+ address: granteeInfo.granteeAddress,
2757
+ publicKey: granteeInfo.publicKey,
2758
+ permissionIds: []
2759
+ // TypeScript infers number[] from Grantee type
2760
+ };
2761
+ return grantee;
2762
+ } catch (error) {
2763
+ console.warn(`Failed to fetch grantee ${granteeId}:`, error);
2764
+ return null;
2765
+ }
2766
+ }
2767
+ );
2768
+ const granteeInfoResults = await Promise.all(granteeInfoPromises);
2769
+ grantees = granteeInfoResults.filter(
2770
+ (grantee) => grantee !== null
2771
+ );
2541
2772
  }
2542
2773
  return {
2543
2774
  grantees,
@@ -2548,15 +2779,16 @@ class PermissionsController extends import_base.BaseController {
2548
2779
  };
2549
2780
  }
2550
2781
  /**
2551
- * Retrieves a specific grantee by their Ethereum address from the DataPortabilityGrantees contract.
2782
+ * Retrieves a specific grantee by their Ethereum wallet address.
2552
2783
  *
2784
+ * @remarks
2553
2785
  * Looks up a registered grantee (application) using their Ethereum address
2554
- * and returns their complete registration information including permissions.
2786
+ * and returns their complete registration information including all associated permissions.
2555
2787
  *
2556
- * @param granteeAddress - The Ethereum address of the grantee to look up
2557
- * @returns Promise resolving to the grantee information, or null if not found
2558
- * @throws {BlockchainError} When contract read operation fails
2559
- * @throws {NetworkError} When unable to connect to the blockchain network
2788
+ * Returns `null` if the address is not registered as a grantee or if an error occurs.
2789
+ *
2790
+ * @param granteeAddress - Ethereum wallet address of the grantee to query
2791
+ * @returns Grantee information including ID, addresses, public key, and permission IDs, or `null` if not found
2560
2792
  *
2561
2793
  * @example
2562
2794
  * ```typescript
@@ -2581,40 +2813,32 @@ class PermissionsController extends import_base.BaseController {
2581
2813
  );
2582
2814
  const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
2583
2815
  try {
2584
- const granteeInfo = await this.context.publicClient.readContract({
2585
- address: DataPortabilityGranteesAddress,
2586
- abi: DataPortabilityGranteesAbi,
2587
- functionName: "granteeByAddress",
2588
- args: [granteeAddress]
2589
- });
2590
2816
  const granteeId = await this.context.publicClient.readContract({
2591
2817
  address: DataPortabilityGranteesAddress,
2592
2818
  abi: DataPortabilityGranteesAbi,
2593
2819
  functionName: "granteeAddressToId",
2594
2820
  args: [granteeAddress]
2595
2821
  });
2596
- return {
2597
- id: Number(granteeId),
2598
- owner: granteeInfo.owner,
2599
- address: granteeInfo.granteeAddress,
2600
- publicKey: granteeInfo.publicKey,
2601
- permissionIds: granteeInfo.permissionIds.map((id) => Number(id))
2602
- };
2822
+ if (granteeId === 0n) {
2823
+ return null;
2824
+ }
2825
+ return await this.getGranteeById(Number(granteeId));
2603
2826
  } catch (error) {
2604
2827
  console.warn(`Failed to fetch grantee ${granteeAddress}:`, error);
2605
2828
  return null;
2606
2829
  }
2607
2830
  }
2608
2831
  /**
2609
- * Retrieves a specific grantee by their unique ID from the DataPortabilityGrantees contract.
2832
+ * Retrieves a specific grantee by their unique ID.
2610
2833
  *
2834
+ * @remarks
2611
2835
  * Looks up a registered grantee (application) using their numeric ID assigned during
2612
- * registration and returns their complete information including permissions.
2836
+ * registration and returns their complete information including all associated permissions.
2613
2837
  *
2614
- * @param granteeId - The unique numeric ID of the grantee (1-indexed)
2615
- * @returns Promise resolving to the grantee information, or null if not found
2616
- * @throws {BlockchainError} When contract read operation fails
2617
- * @throws {NetworkError} When unable to connect to the blockchain network
2838
+ * Returns `null` if the grantee is not found or if an error occurs during fetching.
2839
+ *
2840
+ * @param granteeId - Unique numeric ID of the grantee (1-indexed)
2841
+ * @returns Grantee information including ID, addresses, public key, and permission IDs, or `null` if not found
2618
2842
  *
2619
2843
  * @example
2620
2844
  * ```typescript
@@ -2622,7 +2846,7 @@ class PermissionsController extends import_base.BaseController {
2622
2846
  *
2623
2847
  * if (grantee) {
2624
2848
  * console.log(`Grantee ID: ${grantee.id}`);
2625
- * console.log(`Address: ${grantee.granteeAddress}`);
2849
+ * console.log(`Address: ${grantee.address}`);
2626
2850
  * console.log(`Owner: ${grantee.owner}`);
2627
2851
  * console.log(`Total permissions: ${grantee.permissionIds.length}`);
2628
2852
  * } else {
@@ -2638,18 +2862,23 @@ class PermissionsController extends import_base.BaseController {
2638
2862
  );
2639
2863
  const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
2640
2864
  try {
2641
- const granteeInfo = await this.context.publicClient.readContract({
2865
+ const granteeInfoResult = await this.context.publicClient.readContract({
2642
2866
  address: DataPortabilityGranteesAddress,
2643
2867
  abi: DataPortabilityGranteesAbi,
2644
- functionName: "grantees",
2868
+ functionName: "granteesV2",
2645
2869
  args: [BigInt(granteeId)]
2646
2870
  });
2871
+ const granteeInfo = granteeInfoResult;
2872
+ const allPermissionIdsResult = await this.getGranteePermissionsPaginated(
2873
+ BigInt(granteeId)
2874
+ );
2875
+ const allPermissionIds = allPermissionIdsResult;
2647
2876
  return {
2648
2877
  id: granteeId,
2649
2878
  owner: granteeInfo.owner,
2650
2879
  address: granteeInfo.granteeAddress,
2651
2880
  publicKey: granteeInfo.publicKey,
2652
- permissionIds: granteeInfo.permissionIds.map((id) => Number(id))
2881
+ permissionIds: allPermissionIds.map((id) => Number(id))
2653
2882
  };
2654
2883
  } catch (error) {
2655
2884
  console.warn(`Failed to fetch grantee ${granteeId}:`, error);
@@ -3046,6 +3275,31 @@ class PermissionsController extends import_base.BaseController {
3046
3275
  );
3047
3276
  }
3048
3277
  }
3278
+ /**
3279
+ * Retrieves detailed grant file data from IPFS or HTTP storage.
3280
+ *
3281
+ * @remarks
3282
+ * This method automatically uses the SDK's configured downloadRelayer to bypass CORS restrictions.
3283
+ * Use this instead of importing the standalone `retrieveGrantFile` utility.
3284
+ *
3285
+ * @param grantUrl - The grant file URL (from OnChainPermissionGrant.grantUrl)
3286
+ * @returns Promise resolving to the complete grant file with operation details
3287
+ * @throws {NetworkError} When all retrieval attempts fail
3288
+ * @example
3289
+ * ```typescript
3290
+ * const grants = await vana.permissions.getUserPermissionGrantsOnChain();
3291
+ * const grantFile = await vana.permissions.retrieveGrantFile(grants[0].grantUrl);
3292
+ * console.log(`Operation: ${grantFile.operation}`);
3293
+ * ```
3294
+ */
3295
+ async retrieveGrantFile(grantUrl) {
3296
+ const { retrieveGrantFile: retrieveGrantFileUtil } = await import("../utils/grantFiles");
3297
+ return retrieveGrantFileUtil(
3298
+ grantUrl,
3299
+ void 0,
3300
+ this.context.downloadRelayer
3301
+ );
3302
+ }
3049
3303
  /**
3050
3304
  * Get all permissions for a specific file (alias for getFilePermissionIds)
3051
3305
  *
@@ -3071,26 +3325,34 @@ class PermissionsController extends import_base.BaseController {
3071
3325
  // DATA PORTABILITY GRANTEES HELPER METHODS
3072
3326
  // ===========================
3073
3327
  /**
3074
- * Get grantee information by grantee ID
3328
+ * Retrieves detailed grantee information including all associated permissions.
3329
+ *
3330
+ * @remarks
3331
+ * Returns grantee metadata and associated permission IDs. Uses the newer
3332
+ * paginated contract method internally for efficient permission fetching.
3075
3333
  *
3076
- * @param granteeId - Grantee ID to get info for
3077
- * @returns Promise resolving to grantee info
3334
+ * @param granteeId - Unique grantee identifier as bigint
3335
+ * @returns Grantee information containing owner address, grantee address, public key, and permission IDs
3336
+ * @throws {BlockchainError} When grantee ID is not found or contract read fails
3337
+ *
3338
+ * @example
3339
+ * ```typescript
3340
+ * const granteeInfo = await vana.permissions.getGranteeInfo(BigInt(1));
3341
+ * console.log(`Grantee ${granteeInfo.granteeAddress} has ${granteeInfo.permissionIds.length} permissions`);
3342
+ * ```
3078
3343
  */
3079
3344
  async getGranteeInfo(granteeId) {
3080
3345
  try {
3081
- const chainId = await this.context.publicClient.getChainId();
3082
- const DataPortabilityGranteesAddress = (0, import_addresses.getContractAddress)(
3083
- chainId,
3084
- "DataPortabilityGrantees"
3085
- );
3086
- const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
3087
- const granteeInfo = await this.context.publicClient.readContract({
3088
- address: DataPortabilityGranteesAddress,
3089
- abi: DataPortabilityGranteesAbi,
3090
- functionName: "granteeInfo",
3091
- args: [granteeId]
3092
- });
3093
- return granteeInfo;
3346
+ const grantee = await this.getGranteeById(Number(granteeId));
3347
+ if (!grantee) {
3348
+ throw new Error("Grantee not found");
3349
+ }
3350
+ return {
3351
+ owner: grantee.owner,
3352
+ granteeAddress: grantee.address,
3353
+ publicKey: grantee.publicKey,
3354
+ permissionIds: grantee.permissionIds.map((id) => BigInt(id))
3355
+ };
3094
3356
  } catch (error) {
3095
3357
  throw new import_errors.BlockchainError(
3096
3358
  `Failed to get grantee info: ${error instanceof Error ? error.message : "Unknown error"}`,
@@ -3099,10 +3361,21 @@ class PermissionsController extends import_base.BaseController {
3099
3361
  }
3100
3362
  }
3101
3363
  /**
3102
- * Get grantee information by grantee address
3364
+ * Retrieves detailed grantee information by wallet address.
3365
+ *
3366
+ * @remarks
3367
+ * Looks up the grantee ID from the provided address, then fetches complete
3368
+ * grantee information including all associated permissions.
3369
+ *
3370
+ * @param granteeAddress - Ethereum wallet address of the grantee to query
3371
+ * @returns Grantee information containing owner address, grantee address, public key, and permission IDs
3372
+ * @throws {BlockchainError} When grantee address is not registered or contract read fails
3103
3373
  *
3104
- * @param granteeAddress - Grantee address to get info for
3105
- * @returns Promise resolving to grantee info
3374
+ * @example
3375
+ * ```typescript
3376
+ * const granteeInfo = await vana.permissions.getGranteeInfoByAddress("0x742d35Cc6634c0532925a3b844Bc9e8e1ee3b2De");
3377
+ * console.log(`Found grantee with ${granteeInfo.permissionIds.length} permissions`);
3378
+ * ```
3106
3379
  */
3107
3380
  async getGranteeInfoByAddress(granteeAddress) {
3108
3381
  try {
@@ -3112,13 +3385,26 @@ class PermissionsController extends import_base.BaseController {
3112
3385
  "DataPortabilityGrantees"
3113
3386
  );
3114
3387
  const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
3115
- const granteeInfo = await this.context.publicClient.readContract({
3388
+ const granteeIdResult = await this.context.publicClient.readContract({
3116
3389
  address: DataPortabilityGranteesAddress,
3117
3390
  abi: DataPortabilityGranteesAbi,
3118
- functionName: "granteeByAddress",
3391
+ functionName: "granteeAddressToId",
3119
3392
  args: [granteeAddress]
3120
3393
  });
3121
- return granteeInfo;
3394
+ const granteeId = granteeIdResult;
3395
+ if (granteeId === 0n) {
3396
+ throw new Error("Grantee not found");
3397
+ }
3398
+ const grantee = await this.getGranteeById(Number(granteeId));
3399
+ if (!grantee) {
3400
+ throw new Error("Grantee not found");
3401
+ }
3402
+ return {
3403
+ owner: grantee.owner,
3404
+ granteeAddress: grantee.address,
3405
+ publicKey: grantee.publicKey,
3406
+ permissionIds: grantee.permissionIds.map((id) => BigInt(id))
3407
+ };
3122
3408
  } catch (error) {
3123
3409
  throw new import_errors.BlockchainError(
3124
3410
  `Failed to get grantee info by address: ${error instanceof Error ? error.message : "Unknown error"}`,
@@ -3182,6 +3468,117 @@ class PermissionsController extends import_base.BaseController {
3182
3468
  );
3183
3469
  }
3184
3470
  }
3471
+ /**
3472
+ * Retrieves permission IDs for a specific grantee with flexible pagination.
3473
+ *
3474
+ * @remarks
3475
+ * **Pagination Behavior:**
3476
+ * Returns different types based on parameters:
3477
+ * - Without offset/limit: Returns `bigint[]` of all permissions using batched multicall
3478
+ * - With offset/limit: Returns paginated object with `permissionIds`, `totalCount`, and `hasMore`
3479
+ *
3480
+ * Uses gas-aware multicall for efficient batch fetching when retrieving all permissions.
3481
+ *
3482
+ * @param granteeId - Grantee ID to get permissions for
3483
+ * @param options - Optional pagination parameters
3484
+ * @param options.offset - Zero-based starting index for pagination. Defaults to 0 when fetching all permissions. Required for single-page requests.
3485
+ * @param options.limit - Maximum number of permission IDs to return per page. Defaults to 100 when fetching all permissions. Required for single-page requests.
3486
+ * @returns When called without options: Array of all permission IDs as `bigint[]`.
3487
+ * When called with offset and limit: Paginated result object containing `permissionIds` array,
3488
+ * `totalCount`, and `hasMore` boolean.
3489
+ * @throws {BlockchainError} When contract read operation fails
3490
+ *
3491
+ * @example
3492
+ * ```typescript
3493
+ * // Fetch all permissions (no pagination params)
3494
+ * const allPermissions = await vana.permissions.getGranteePermissionsPaginated(BigInt(1));
3495
+ * console.log(`Total permissions: ${allPermissions.length}`);
3496
+ *
3497
+ * // Fetch a specific page (with pagination params)
3498
+ * const page = await vana.permissions.getGranteePermissionsPaginated(BigInt(1), {
3499
+ * offset: BigInt(0),
3500
+ * limit: BigInt(100)
3501
+ * });
3502
+ * console.log(`Fetched ${page.permissionIds.length} permissions`);
3503
+ * console.log(`Total: ${page.totalCount}, Has more: ${page.hasMore}`);
3504
+ *
3505
+ * // Fetch next page
3506
+ * if (page.hasMore) {
3507
+ * const nextPage = await vana.permissions.getGranteePermissionsPaginated(BigInt(1), {
3508
+ * offset: BigInt(100),
3509
+ * limit: BigInt(100)
3510
+ * });
3511
+ * }
3512
+ * ```
3513
+ */
3514
+ async getGranteePermissionsPaginated(granteeId, options) {
3515
+ try {
3516
+ const chainId = await this.context.publicClient.getChainId();
3517
+ const DataPortabilityGranteesAddress = (0, import_addresses.getContractAddress)(
3518
+ chainId,
3519
+ "DataPortabilityGrantees"
3520
+ );
3521
+ const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
3522
+ const fetchOnlyOnePage = options?.offset !== void 0 && options?.limit !== void 0;
3523
+ if (fetchOnlyOnePage) {
3524
+ const result = await this.context.publicClient.readContract({
3525
+ address: DataPortabilityGranteesAddress,
3526
+ abi: DataPortabilityGranteesAbi,
3527
+ functionName: "granteePermissionsPaginated",
3528
+ args: [granteeId, options.offset, options.limit]
3529
+ });
3530
+ const [permissionIds, totalCount2, hasMore] = result;
3531
+ return {
3532
+ permissionIds: [...permissionIds],
3533
+ totalCount: totalCount2,
3534
+ hasMore
3535
+ };
3536
+ }
3537
+ const countResult = await this.context.publicClient.readContract({
3538
+ address: DataPortabilityGranteesAddress,
3539
+ abi: DataPortabilityGranteesAbi,
3540
+ functionName: "granteePermissionsPaginated",
3541
+ args: [granteeId, BigInt(0), BigInt(1)]
3542
+ });
3543
+ const [, totalCount] = countResult;
3544
+ if (totalCount === BigInt(0)) {
3545
+ return [];
3546
+ }
3547
+ const batchSize = options?.limit ?? BigInt(100);
3548
+ const startOffset = options?.offset ?? BigInt(0);
3549
+ const endOffset = totalCount;
3550
+ const numBatches = Math.ceil(
3551
+ Number(endOffset - startOffset) / Number(batchSize)
3552
+ );
3553
+ const paginationCalls = Array.from({ length: numBatches }, (_, i) => ({
3554
+ address: DataPortabilityGranteesAddress,
3555
+ abi: DataPortabilityGranteesAbi,
3556
+ functionName: "granteePermissionsPaginated",
3557
+ args: [
3558
+ granteeId,
3559
+ startOffset + BigInt(i) * batchSize,
3560
+ batchSize
3561
+ ]
3562
+ }));
3563
+ const results = await (0, import_multicall.gasAwareMulticall)(
3564
+ this.context.publicClient,
3565
+ {
3566
+ contracts: paginationCalls
3567
+ }
3568
+ );
3569
+ const allPermissionIds = [];
3570
+ for (const result of results) {
3571
+ const [permissionIds] = result;
3572
+ allPermissionIds.push(...permissionIds);
3573
+ }
3574
+ return allPermissionIds;
3575
+ } catch (error) {
3576
+ throw new import_errors.BlockchainError(
3577
+ `Failed to get grantee permissions: ${error instanceof Error ? error.message : "Unknown error"}`,
3578
+ error
3579
+ );
3580
+ }
3581
+ }
3185
3582
  // ===== DataPortabilityServersImplementation Methods =====
3186
3583
  /**
3187
3584
  * Get all server IDs for a user
@@ -3395,7 +3792,7 @@ class PermissionsController extends import_base.BaseController {
3395
3792
  args: [serverId, url],
3396
3793
  chain: this.context.walletClient?.chain,
3397
3794
  account,
3398
- ...options?.gasLimit && { gas: options.gasLimit },
3795
+ ...options?.gas && { gas: options.gas },
3399
3796
  ...options?.nonce && { nonce: options.nonce },
3400
3797
  // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
3401
3798
  ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
@@ -3601,7 +3998,7 @@ class PermissionsController extends import_base.BaseController {
3601
3998
  * @throws {BlockchainError} When permission addition fails
3602
3999
  * @throws {NetworkError} When network communication fails
3603
4000
  */
3604
- async submitSignedAddPermission(typedData, signature) {
4001
+ async submitSignedAddPermission(typedData, signature, options) {
3605
4002
  this.assertWallet();
3606
4003
  try {
3607
4004
  let hash;
@@ -3616,7 +4013,9 @@ class PermissionsController extends import_base.BaseController {
3616
4013
  if (response.type === "error") {
3617
4014
  throw new import_errors.RelayerError(response.error);
3618
4015
  }
3619
- if (response.type === "signed") {
4016
+ if (response.type === "submitted") {
4017
+ hash = response.hash;
4018
+ } else if (response.type === "signed") {
3620
4019
  hash = response.hash;
3621
4020
  } else {
3622
4021
  throw new Error("Unexpected response type from relayer");
@@ -3624,7 +4023,8 @@ class PermissionsController extends import_base.BaseController {
3624
4023
  } else {
3625
4024
  hash = await this.submitDirectAddPermissionTransaction(
3626
4025
  typedData,
3627
- signature
4026
+ signature,
4027
+ options
3628
4028
  );
3629
4029
  }
3630
4030
  const account = this.context.walletClient?.account ?? this.context.userAddress;
@@ -3793,7 +4193,9 @@ class PermissionsController extends import_base.BaseController {
3793
4193
  if (response.type === "error") {
3794
4194
  throw new import_errors.RelayerError(response.error);
3795
4195
  }
3796
- if (response.type === "signed") {
4196
+ if (response.type === "submitted") {
4197
+ hash = response.hash;
4198
+ } else if (response.type === "signed") {
3797
4199
  hash = response.hash;
3798
4200
  } else {
3799
4201
  throw new Error("Unexpected response type from relayer");
@@ -3855,7 +4257,7 @@ class PermissionsController extends import_base.BaseController {
3855
4257
  args: [permissionId],
3856
4258
  chain: this.context.walletClient?.chain,
3857
4259
  account,
3858
- ...options?.gasLimit && { gas: options.gasLimit },
4260
+ ...options?.gas && { gas: options.gas },
3859
4261
  ...options?.nonce && { nonce: options.nonce },
3860
4262
  // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
3861
4263
  ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
@@ -3888,7 +4290,7 @@ class PermissionsController extends import_base.BaseController {
3888
4290
  * @param signature - The cryptographic signature authorizing the transaction
3889
4291
  * @returns Promise resolving to the transaction hash
3890
4292
  */
3891
- async submitDirectAddPermissionTransaction(typedData, signature) {
4293
+ async submitDirectAddPermissionTransaction(typedData, signature, options) {
3892
4294
  this.assertWallet();
3893
4295
  const chainId = await this.context.walletClient.getChainId();
3894
4296
  const DataPortabilityPermissionsAddress = (0, import_addresses.getContractAddress)(
@@ -3909,7 +4311,8 @@ class PermissionsController extends import_base.BaseController {
3909
4311
  functionName: "addPermission",
3910
4312
  args: [permissionInput, formattedSignature],
3911
4313
  account: this.context.walletClient?.account ?? this.context.userAddress,
3912
- chain: this.context.walletClient?.chain ?? null
4314
+ chain: this.context.walletClient?.chain ?? null,
4315
+ ...this.spreadTransactionOptions(options)
3913
4316
  });
3914
4317
  return hash;
3915
4318
  }
@@ -3944,22 +4347,11 @@ class PermissionsController extends import_base.BaseController {
3944
4347
  address: DataPortabilityPermissionsAddress,
3945
4348
  abi: DataPortabilityPermissionsAbi,
3946
4349
  functionName: "addServerFilesAndPermissions",
3947
- // @ts-expect-error - Viem's type inference for nested Permission[][] arrays is incompatible with our Permission type
3948
4350
  args: [serverFilesAndPermissionInput, formattedSignature],
3949
4351
  account: this.context.walletClient?.account ?? this.context.userAddress,
3950
4352
  chain: this.context.walletClient?.chain ?? null,
3951
- ...options?.gasLimit && { gas: options.gasLimit },
3952
- ...options?.nonce && { nonce: options.nonce },
3953
4353
  ...options?.value && { value: options.value },
3954
- // Use EIP-1559 if available, otherwise fall back to legacy gasPrice
3955
- ...options?.maxFeePerGas || options?.maxPriorityFeePerGas ? {
3956
- ...options.maxFeePerGas && {
3957
- maxFeePerGas: options.maxFeePerGas
3958
- },
3959
- ...options.maxPriorityFeePerGas && {
3960
- maxPriorityFeePerGas: options.maxPriorityFeePerGas
3961
- }
3962
- } : options?.gasPrice && { gasPrice: options.gasPrice }
4354
+ ...this.spreadTransactionOptions(options)
3963
4355
  });
3964
4356
  return hash;
3965
4357
  }