@opendatalabs/vana-sdk 0.1.0-alpha.2b6935d → 0.1.0-alpha.2e569eb

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 (292) 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/config/chains.cjs.map +1 -1
  8. package/dist/config/chains.d.ts +99 -0
  9. package/dist/config/chains.js.map +1 -1
  10. package/dist/contracts/contractController.cjs.map +1 -1
  11. package/dist/contracts/contractController.d.ts +66 -10
  12. package/dist/contracts/contractController.js.map +1 -1
  13. package/dist/controllers/__tests__/data-consistency-integration.test.d.ts +7 -0
  14. package/dist/controllers/base.cjs +33 -0
  15. package/dist/controllers/base.cjs.map +1 -1
  16. package/dist/controllers/base.d.ts +10 -0
  17. package/dist/controllers/base.js +33 -0
  18. package/dist/controllers/base.js.map +1 -1
  19. package/dist/controllers/data.cjs +417 -276
  20. package/dist/controllers/data.cjs.map +1 -1
  21. package/dist/controllers/data.d.ts +246 -193
  22. package/dist/controllers/data.js +430 -279
  23. package/dist/controllers/data.js.map +1 -1
  24. package/dist/controllers/operations.cjs +430 -0
  25. package/dist/controllers/operations.cjs.map +1 -0
  26. package/dist/controllers/operations.d.ts +229 -0
  27. package/dist/controllers/operations.js +406 -0
  28. package/dist/controllers/operations.js.map +1 -0
  29. package/dist/controllers/permissions.cjs +691 -210
  30. package/dist/controllers/permissions.cjs.map +1 -1
  31. package/dist/controllers/permissions.d.ts +196 -68
  32. package/dist/controllers/permissions.js +691 -210
  33. package/dist/controllers/permissions.js.map +1 -1
  34. package/dist/controllers/protocol.cjs.map +1 -1
  35. package/dist/controllers/protocol.d.ts +27 -28
  36. package/dist/controllers/protocol.js.map +1 -1
  37. package/dist/controllers/schemas.cjs +104 -25
  38. package/dist/controllers/schemas.cjs.map +1 -1
  39. package/dist/controllers/schemas.d.ts +88 -40
  40. package/dist/controllers/schemas.js +104 -25
  41. package/dist/controllers/schemas.js.map +1 -1
  42. package/dist/controllers/server.cjs +269 -58
  43. package/dist/controllers/server.cjs.map +1 -1
  44. package/dist/controllers/server.d.ts +157 -52
  45. package/dist/controllers/server.js +269 -58
  46. package/dist/controllers/server.js.map +1 -1
  47. package/dist/core/__tests__/health.test.d.ts +1 -0
  48. package/dist/core/__tests__/inMemoryNonceManager.test.d.ts +1 -0
  49. package/dist/core/__tests__/nonceManager.test.d.ts +1 -0
  50. package/dist/core/__tests__/pollingManager.test.d.ts +4 -0
  51. package/dist/core/apiClient.cjs +53 -3
  52. package/dist/core/apiClient.cjs.map +1 -1
  53. package/dist/core/apiClient.d.ts +132 -7
  54. package/dist/core/apiClient.js +53 -3
  55. package/dist/core/apiClient.js.map +1 -1
  56. package/dist/core/generics.cjs +30 -3
  57. package/dist/core/generics.cjs.map +1 -1
  58. package/dist/core/generics.d.ts +95 -6
  59. package/dist/core/generics.js +30 -3
  60. package/dist/core/generics.js.map +1 -1
  61. package/dist/core/health.cjs +289 -0
  62. package/dist/core/health.cjs.map +1 -0
  63. package/dist/core/health.d.ts +143 -0
  64. package/dist/core/health.js +265 -0
  65. package/dist/core/health.js.map +1 -0
  66. package/dist/core/inMemoryNonceManager.cjs +138 -0
  67. package/dist/core/inMemoryNonceManager.cjs.map +1 -0
  68. package/dist/core/inMemoryNonceManager.d.ts +69 -0
  69. package/dist/core/inMemoryNonceManager.js +114 -0
  70. package/dist/core/inMemoryNonceManager.js.map +1 -0
  71. package/dist/core/nonceManager.cjs +304 -0
  72. package/dist/core/nonceManager.cjs.map +1 -0
  73. package/dist/core/nonceManager.d.ts +116 -0
  74. package/dist/core/nonceManager.js +280 -0
  75. package/dist/core/nonceManager.js.map +1 -0
  76. package/dist/core/pollingManager.cjs +292 -0
  77. package/dist/core/pollingManager.cjs.map +1 -0
  78. package/dist/core/pollingManager.d.ts +120 -0
  79. package/dist/core/pollingManager.js +268 -0
  80. package/dist/core/pollingManager.js.map +1 -0
  81. package/dist/core.cjs +9 -1
  82. package/dist/core.cjs.map +1 -1
  83. package/dist/core.d.ts +10 -3
  84. package/dist/core.js +9 -1
  85. package/dist/core.js.map +1 -1
  86. package/dist/crypto/ecies/base.cjs +16 -3
  87. package/dist/crypto/ecies/base.cjs.map +1 -1
  88. package/dist/crypto/ecies/base.js +16 -3
  89. package/dist/crypto/ecies/base.js.map +1 -1
  90. package/dist/errors.cjs +29 -0
  91. package/dist/errors.cjs.map +1 -1
  92. package/dist/errors.d.ts +64 -0
  93. package/dist/errors.js +28 -0
  94. package/dist/errors.js.map +1 -1
  95. package/dist/generated/abi/DataPortabilityGranteesImplementation.cjs +162 -0
  96. package/dist/generated/abi/DataPortabilityGranteesImplementation.cjs.map +1 -1
  97. package/dist/generated/abi/DataPortabilityGranteesImplementation.d.ts +123 -0
  98. package/dist/generated/abi/DataPortabilityGranteesImplementation.js +162 -0
  99. package/dist/generated/abi/DataPortabilityGranteesImplementation.js.map +1 -1
  100. package/dist/generated/abi/index.d.ts +123 -0
  101. package/dist/generated/server/server-exports.cjs +22 -0
  102. package/dist/generated/server/server-exports.cjs.map +1 -1
  103. package/dist/generated/server/server-exports.d.ts +27 -10
  104. package/dist/generated/server/server-exports.js +17 -0
  105. package/dist/generated/server/server-exports.js.map +1 -1
  106. package/dist/generated/server/server.cjs.map +1 -1
  107. package/dist/generated/server/server.d.ts +771 -402
  108. package/dist/generated/subgraph.cjs +797 -32
  109. package/dist/generated/subgraph.cjs.map +1 -1
  110. package/dist/generated/subgraph.d.ts +135 -0
  111. package/dist/generated/subgraph.js +792 -32
  112. package/dist/generated/subgraph.js.map +1 -1
  113. package/dist/index.browser.d.ts +1 -0
  114. package/dist/index.browser.js +2 -0
  115. package/dist/index.browser.js.map +1 -1
  116. package/dist/index.cjs.map +1 -1
  117. package/dist/index.js.map +1 -1
  118. package/dist/index.node.cjs +19 -3
  119. package/dist/index.node.cjs.map +1 -1
  120. package/dist/index.node.d.ts +54 -14
  121. package/dist/index.node.js +17 -3
  122. package/dist/index.node.js.map +1 -1
  123. package/dist/lib/__tests__/redisAtomicStore.test.d.ts +1 -0
  124. package/dist/lib/redisAtomicStore.cjs +201 -0
  125. package/dist/lib/redisAtomicStore.cjs.map +1 -0
  126. package/dist/lib/redisAtomicStore.d.ts +120 -0
  127. package/dist/lib/redisAtomicStore.js +177 -0
  128. package/dist/lib/redisAtomicStore.js.map +1 -0
  129. package/dist/node.cjs.map +1 -1
  130. package/dist/node.d.ts +39 -1
  131. package/dist/node.js.map +1 -1
  132. package/dist/platform/browser.cjs +160 -2
  133. package/dist/platform/browser.cjs.map +1 -1
  134. package/dist/platform/browser.d.ts +232 -12
  135. package/dist/platform/browser.js +160 -2
  136. package/dist/platform/browser.js.map +1 -1
  137. package/dist/platform/interface.cjs.map +1 -1
  138. package/dist/platform/interface.d.ts +283 -90
  139. package/dist/platform/node.cjs +163 -2
  140. package/dist/platform/node.cjs.map +1 -1
  141. package/dist/platform/node.d.ts +69 -6
  142. package/dist/platform/node.js +163 -2
  143. package/dist/platform/node.js.map +1 -1
  144. package/dist/server/relayerHandler.cjs +295 -95
  145. package/dist/server/relayerHandler.cjs.map +1 -1
  146. package/dist/server/relayerHandler.d.ts +35 -3
  147. package/dist/server/relayerHandler.js +294 -93
  148. package/dist/server/relayerHandler.js.map +1 -1
  149. package/dist/storage/index.cjs +3 -0
  150. package/dist/storage/index.cjs.map +1 -1
  151. package/dist/storage/index.d.ts +1 -0
  152. package/dist/storage/index.js +2 -0
  153. package/dist/storage/index.js.map +1 -1
  154. package/dist/storage/manager.cjs +108 -25
  155. package/dist/storage/manager.cjs.map +1 -1
  156. package/dist/storage/manager.d.ts +119 -25
  157. package/dist/storage/manager.js +108 -25
  158. package/dist/storage/manager.js.map +1 -1
  159. package/dist/storage/providers/callback-storage.cjs +86 -15
  160. package/dist/storage/providers/callback-storage.cjs.map +1 -1
  161. package/dist/storage/providers/callback-storage.d.ts +109 -20
  162. package/dist/storage/providers/callback-storage.js +86 -15
  163. package/dist/storage/providers/callback-storage.js.map +1 -1
  164. package/dist/storage/providers/dropbox.cjs +237 -0
  165. package/dist/storage/providers/dropbox.cjs.map +1 -0
  166. package/dist/storage/providers/dropbox.d.ts +39 -0
  167. package/dist/storage/providers/dropbox.js +215 -0
  168. package/dist/storage/providers/dropbox.js.map +1 -0
  169. package/dist/storage/providers/dropbox.test.d.ts +1 -0
  170. package/dist/storage/providers/pinata.cjs.map +1 -1
  171. package/dist/storage/providers/pinata.d.ts +12 -14
  172. package/dist/storage/providers/pinata.js.map +1 -1
  173. package/dist/tests/data-upload-owner-validation.test.d.ts +1 -0
  174. package/dist/tests/permissions-transaction-options.test.d.ts +1 -0
  175. package/dist/types/atomicStore.cjs +31 -0
  176. package/dist/types/atomicStore.cjs.map +1 -0
  177. package/dist/types/atomicStore.d.ts +236 -0
  178. package/dist/types/atomicStore.js +7 -0
  179. package/dist/types/atomicStore.js.map +1 -0
  180. package/dist/types/blockchain.cjs.map +1 -1
  181. package/dist/types/blockchain.d.ts +39 -11
  182. package/dist/types/chains.cjs.map +1 -1
  183. package/dist/types/chains.d.ts +74 -7
  184. package/dist/types/chains.js.map +1 -1
  185. package/dist/types/config.cjs.map +1 -1
  186. package/dist/types/config.d.ts +38 -4
  187. package/dist/types/config.js.map +1 -1
  188. package/dist/types/contracts.cjs.map +1 -1
  189. package/dist/types/contracts.d.ts +71 -7
  190. package/dist/types/controller-context.cjs.map +1 -1
  191. package/dist/types/controller-context.d.ts +4 -1
  192. package/dist/types/data.cjs.map +1 -1
  193. package/dist/types/data.d.ts +11 -10
  194. package/dist/types/generics.cjs.map +1 -1
  195. package/dist/types/generics.d.ts +81 -10
  196. package/dist/types/index.cjs.map +1 -1
  197. package/dist/types/index.d.ts +31 -3
  198. package/dist/types/index.js.map +1 -1
  199. package/dist/types/operationStore.cjs +17 -0
  200. package/dist/types/operationStore.cjs.map +1 -0
  201. package/dist/types/operationStore.d.ts +171 -0
  202. package/dist/types/operationStore.js +1 -0
  203. package/dist/types/operationStore.js.map +1 -0
  204. package/dist/types/operations.cjs +3 -15
  205. package/dist/types/operations.cjs.map +1 -1
  206. package/dist/types/operations.d.ts +131 -39
  207. package/dist/types/operations.js +2 -13
  208. package/dist/types/operations.js.map +1 -1
  209. package/dist/types/options.cjs +17 -0
  210. package/dist/types/options.cjs.map +1 -0
  211. package/dist/types/options.d.ts +308 -0
  212. package/dist/types/options.js +1 -0
  213. package/dist/types/options.js.map +1 -0
  214. package/dist/types/permissions.cjs.map +1 -1
  215. package/dist/types/permissions.d.ts +19 -20
  216. package/dist/types/personal.cjs.map +1 -1
  217. package/dist/types/personal.d.ts +150 -14
  218. package/dist/types/relayer.cjs.map +1 -1
  219. package/dist/types/relayer.d.ts +120 -24
  220. package/dist/types/storage.cjs.map +1 -1
  221. package/dist/types/storage.d.ts +9 -21
  222. package/dist/types/storage.js.map +1 -1
  223. package/dist/types/utils.cjs.map +1 -1
  224. package/dist/types/utils.d.ts +0 -45
  225. package/dist/utils/__tests__/chainQuery.test.d.ts +1 -0
  226. package/dist/utils/__tests__/subgraphConsistency.test.d.ts +4 -0
  227. package/dist/utils/__tests__/subgraphPagination.test.d.ts +4 -0
  228. package/dist/utils/chainQuery.cjs +107 -0
  229. package/dist/utils/chainQuery.cjs.map +1 -0
  230. package/dist/utils/chainQuery.d.ts +31 -0
  231. package/dist/utils/chainQuery.js +82 -0
  232. package/dist/utils/chainQuery.js.map +1 -0
  233. package/dist/utils/grantFiles.cjs +4 -1
  234. package/dist/utils/grantFiles.cjs.map +1 -1
  235. package/dist/utils/grantFiles.d.ts +10 -20
  236. package/dist/utils/grantFiles.js +4 -1
  237. package/dist/utils/grantFiles.js.map +1 -1
  238. package/dist/utils/grantValidation.cjs.map +1 -1
  239. package/dist/utils/grantValidation.d.ts +95 -16
  240. package/dist/utils/grantValidation.js.map +1 -1
  241. package/dist/utils/grants.cjs.map +1 -1
  242. package/dist/utils/grants.d.ts +93 -12
  243. package/dist/utils/grants.js.map +1 -1
  244. package/dist/utils/ipfs.cjs +2 -4
  245. package/dist/utils/ipfs.cjs.map +1 -1
  246. package/dist/utils/ipfs.d.ts +1 -1
  247. package/dist/utils/ipfs.js +2 -4
  248. package/dist/utils/ipfs.js.map +1 -1
  249. package/dist/utils/lazy-import.cjs.map +1 -1
  250. package/dist/utils/lazy-import.d.ts +32 -7
  251. package/dist/utils/lazy-import.js.map +1 -1
  252. package/dist/utils/signatureCache.cjs +8 -2
  253. package/dist/utils/signatureCache.cjs.map +1 -1
  254. package/dist/utils/signatureCache.d.ts +49 -8
  255. package/dist/utils/signatureCache.js +8 -2
  256. package/dist/utils/signatureCache.js.map +1 -1
  257. package/dist/utils/subgraphConsistency.cjs +184 -0
  258. package/dist/utils/subgraphConsistency.cjs.map +1 -0
  259. package/dist/utils/subgraphConsistency.d.ts +65 -0
  260. package/dist/utils/subgraphConsistency.js +155 -0
  261. package/dist/utils/subgraphConsistency.js.map +1 -0
  262. package/dist/utils/subgraphMetaCache.cjs +101 -0
  263. package/dist/utils/subgraphMetaCache.cjs.map +1 -0
  264. package/dist/utils/subgraphMetaCache.d.ts +56 -0
  265. package/dist/utils/subgraphMetaCache.js +76 -0
  266. package/dist/utils/subgraphMetaCache.js.map +1 -0
  267. package/dist/utils/subgraphPagination.cjs +104 -0
  268. package/dist/utils/subgraphPagination.cjs.map +1 -0
  269. package/dist/utils/subgraphPagination.d.ts +78 -0
  270. package/dist/utils/subgraphPagination.js +78 -0
  271. package/dist/utils/subgraphPagination.js.map +1 -0
  272. package/dist/utils/transactionHelpers.cjs.map +1 -1
  273. package/dist/utils/transactionHelpers.d.ts +12 -12
  274. package/dist/utils/transactionHelpers.js.map +1 -1
  275. package/dist/utils/typedDataConverter.cjs.map +1 -1
  276. package/dist/utils/typedDataConverter.d.ts +39 -3
  277. package/dist/utils/typedDataConverter.js.map +1 -1
  278. package/dist/utils/urlResolver.cjs +7 -0
  279. package/dist/utils/urlResolver.cjs.map +1 -1
  280. package/dist/utils/urlResolver.d.ts +22 -4
  281. package/dist/utils/urlResolver.js +7 -0
  282. package/dist/utils/urlResolver.js.map +1 -1
  283. package/dist/utils/wallet.cjs.map +1 -1
  284. package/dist/utils/wallet.d.ts +78 -16
  285. package/dist/utils/wallet.js.map +1 -1
  286. package/package.json +3 -1
  287. package/dist/server/handler.cjs +0 -103
  288. package/dist/server/handler.cjs.map +0 -1
  289. package/dist/server/handler.d.ts +0 -95
  290. package/dist/server/handler.js +0 -79
  291. package/dist/server/handler.js.map +0 -1
  292. /package/dist/{tests/server-handler.test.d.ts → controllers/__tests__/operations.processQueue.test.d.ts} +0 -0
@@ -18,54 +18,254 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var relayerHandler_exports = {};
20
20
  __export(relayerHandler_exports, {
21
- handleRelayerOperation: () => handleRelayerOperation,
22
- handleRelayerRequest: () => import_handler.handleRelayerRequest
21
+ handleRelayerOperation: () => handleRelayerOperation
23
22
  });
24
23
  module.exports = __toCommonJS(relayerHandler_exports);
24
+ var import_uuid = require("uuid");
25
25
  var import_errors = require("../errors");
26
26
  var import_viem = require("viem");
27
- var import_handler = require("./handler");
28
- async function handleRelayerOperation(sdk, request) {
29
- if (request.type === "signed") {
30
- return handleSignedOperation(sdk, request);
27
+ async function handleRelayerOperation(sdk, request, options = {}) {
28
+ const sdkWithStores = sdk;
29
+ const storeUntyped = sdkWithStores.operationStore;
30
+ const isRelayerStore = storeUntyped && "get" in storeUntyped && "set" in storeUntyped;
31
+ const store = isRelayerStore ? storeUntyped : void 0;
32
+ const executionMode = options.execution ?? "sync";
33
+ const syncTimeout = options.syncTimeout ?? 3e4;
34
+ const transactionOptions = options.gas || options.gasPrice || options.maxFeePerGas || options.maxPriorityFeePerGas || options.nonce !== void 0 || options.value || options.signal || options.onStatusUpdate ? {
35
+ ...options.gas && { gas: options.gas },
36
+ ...options.gasPrice && { gasPrice: options.gasPrice },
37
+ ...options.maxFeePerGas && { maxFeePerGas: options.maxFeePerGas },
38
+ ...options.maxPriorityFeePerGas && {
39
+ maxPriorityFeePerGas: options.maxPriorityFeePerGas
40
+ },
41
+ ...options.nonce !== void 0 && { nonce: options.nonce },
42
+ ...options.value && { value: options.value },
43
+ ...options.signal && { signal: options.signal },
44
+ ...options.onStatusUpdate && {
45
+ onStatusUpdate: options.onStatusUpdate
46
+ }
47
+ } : void 0;
48
+ if (store) {
49
+ if (request.type === "status_check") {
50
+ const state = await store.get(request.operationId);
51
+ if (!state) return { type: "error", error: "Operation not found" };
52
+ if (state.status === "confirmed")
53
+ return {
54
+ type: "confirmed",
55
+ hash: state.transactionHash,
56
+ receipt: state.finalReceipt
57
+ };
58
+ if (state.status === "failed")
59
+ return { type: "error", error: state.error ?? "Operation failed" };
60
+ if (state.status === "pending") {
61
+ try {
62
+ const publicClient = sdkWithStores.publicClient;
63
+ if (publicClient) {
64
+ let receipt;
65
+ try {
66
+ receipt = await publicClient.getTransactionReceipt({
67
+ hash: state.transactionHash
68
+ });
69
+ } catch (receiptError) {
70
+ if (receiptError?.name !== "TransactionReceiptNotFoundError") {
71
+ console.warn(
72
+ `\u26A0\uFE0F [Relayer] Unexpected error checking receipt:`,
73
+ receiptError?.message ?? receiptError
74
+ );
75
+ }
76
+ receipt = null;
77
+ }
78
+ if (receipt) {
79
+ const updatedState = {
80
+ ...state,
81
+ status: receipt.status === "success" ? "confirmed" : "failed",
82
+ finalReceipt: receipt,
83
+ ...receipt.status !== "success" && {
84
+ error: "Transaction reverted on chain"
85
+ }
86
+ };
87
+ await store.set(request.operationId, updatedState);
88
+ if (receipt.status === "success") {
89
+ return {
90
+ type: "confirmed",
91
+ hash: state.transactionHash,
92
+ receipt
93
+ };
94
+ } else {
95
+ return {
96
+ type: "error",
97
+ error: "Transaction reverted on chain"
98
+ };
99
+ }
100
+ }
101
+ } else {
102
+ console.warn(
103
+ "\u26A0\uFE0F [Relayer] No public client available for status checking"
104
+ );
105
+ }
106
+ } catch (error) {
107
+ console.error(
108
+ `\u274C [Relayer] Unexpected error in status check:`,
109
+ error
110
+ );
111
+ }
112
+ }
113
+ return { type: "pending", operationId: request.operationId };
114
+ }
115
+ const operationId = (0, import_uuid.v4)();
116
+ if (executionMode === "async") {
117
+ await store.set(operationId, {
118
+ status: "pending",
119
+ transactionHash: "",
120
+ // Will be filled when processed
121
+ originalRequest: request,
122
+ nonce: options?.nonce,
123
+ retryCount: 0,
124
+ lastAttemptedGas: {
125
+ maxFeePerGas: transactionOptions?.maxFeePerGas?.toString(),
126
+ maxPriorityFeePerGas: transactionOptions?.maxPriorityFeePerGas?.toString()
127
+ },
128
+ submittedAt: Date.now()
129
+ });
130
+ console.log(
131
+ `[Relayer] Operation ${operationId} queued for async processing`
132
+ );
133
+ return { type: "pending", operationId };
134
+ }
135
+ try {
136
+ const timeoutPromise = new Promise((_, reject) => {
137
+ setTimeout(() => {
138
+ reject(new Error(`Sync execution timeout after ${syncTimeout}ms`));
139
+ }, syncTimeout);
140
+ });
141
+ const response = await Promise.race([
142
+ routeAndExecuteRequest(sdk, request, transactionOptions),
143
+ timeoutPromise
144
+ ]);
145
+ if (response.type === "signed") {
146
+ await store.set(operationId, {
147
+ status: "confirmed",
148
+ transactionHash: response.hash,
149
+ originalRequest: request,
150
+ nonce: transactionOptions?.nonce,
151
+ retryCount: 0,
152
+ lastAttemptedGas: {
153
+ maxFeePerGas: transactionOptions?.maxFeePerGas?.toString(),
154
+ maxPriorityFeePerGas: transactionOptions?.maxPriorityFeePerGas?.toString()
155
+ },
156
+ submittedAt: Date.now()
157
+ });
158
+ return response;
159
+ } else if (response.type === "direct") {
160
+ return response;
161
+ } else {
162
+ return response;
163
+ }
164
+ } catch (e) {
165
+ const error = e instanceof Error ? e : new Error("Unknown error during operation submission");
166
+ await store.set(operationId, {
167
+ status: "pending",
168
+ transactionHash: "",
169
+ // Will be filled when retried
170
+ originalRequest: request,
171
+ nonce: options?.nonce,
172
+ retryCount: 0,
173
+ lastAttemptedGas: {
174
+ maxFeePerGas: transactionOptions?.maxFeePerGas?.toString(),
175
+ maxPriorityFeePerGas: transactionOptions?.maxPriorityFeePerGas?.toString()
176
+ },
177
+ submittedAt: Date.now(),
178
+ error: error.message
179
+ });
180
+ console.warn(
181
+ `[Relayer] Sync execution failed/timed out, returning pending operationId: ${operationId}`
182
+ );
183
+ return { type: "pending", operationId };
184
+ }
185
+ } else {
186
+ if (request.type === "status_check") {
187
+ return {
188
+ type: "error",
189
+ error: "Stateless relayer does not support operation status checks."
190
+ };
191
+ }
192
+ try {
193
+ const response = await routeAndExecuteRequest(
194
+ sdk,
195
+ request,
196
+ transactionOptions
197
+ );
198
+ if (response.type === "signed") {
199
+ return { type: "submitted", hash: response.hash };
200
+ } else if (response.type === "direct" && response.result && typeof response.result === "object" && "hash" in response.result) {
201
+ return {
202
+ type: "submitted",
203
+ hash: response.result.hash
204
+ };
205
+ } else {
206
+ return response;
207
+ }
208
+ } catch (e) {
209
+ const error = e instanceof Error ? e : new Error("Unknown error during operation submission");
210
+ return { type: "error", error: error.message };
211
+ }
31
212
  }
32
- return handleDirectOperation(sdk, request);
33
213
  }
34
- async function handleSignedOperation(sdk, request) {
35
- const { typedData, signature, expectedUserAddress } = request;
36
- let recoveredAddress;
37
- try {
38
- recoveredAddress = await (0, import_viem.recoverTypedDataAddress)({
39
- domain: {
40
- ...typedData.domain,
41
- chainId: typedData.domain.chainId ? BigInt(typedData.domain.chainId) : void 0
42
- },
43
- types: typedData.types,
44
- primaryType: typedData.primaryType,
45
- message: typedData.message,
46
- signature
47
- });
48
- } catch (error) {
49
- throw new import_errors.SignatureError(
50
- `Signature verification failed: ${error instanceof Error ? error.message : "Unknown error"}`
51
- );
52
- }
53
- if (expectedUserAddress) {
54
- const normalizedExpected = (0, import_viem.getAddress)(expectedUserAddress);
55
- const normalizedSigner = (0, import_viem.getAddress)(recoveredAddress);
56
- if (normalizedSigner !== normalizedExpected) {
214
+ async function routeAndExecuteRequest(sdk, request, options) {
215
+ if (request.type === "signed") {
216
+ const { typedData, signature, expectedUserAddress } = request;
217
+ let recoveredAddress;
218
+ try {
219
+ recoveredAddress = await (0, import_viem.recoverTypedDataAddress)({
220
+ domain: {
221
+ ...typedData.domain,
222
+ chainId: typedData.domain.chainId ? BigInt(typedData.domain.chainId) : void 0
223
+ },
224
+ types: typedData.types,
225
+ primaryType: typedData.primaryType,
226
+ message: typedData.message,
227
+ signature
228
+ });
229
+ } catch (error) {
57
230
  throw new import_errors.SignatureError(
58
- `Security verification failed: Recovered signer address (${normalizedSigner}) does not match expected user address (${normalizedExpected})`
231
+ `Signature verification failed: ${error instanceof Error ? error.message : "Unknown error"}`
59
232
  );
60
233
  }
234
+ if (expectedUserAddress) {
235
+ const normalizedExpected = (0, import_viem.getAddress)(expectedUserAddress);
236
+ const normalizedSigner = (0, import_viem.getAddress)(recoveredAddress);
237
+ if (normalizedSigner !== normalizedExpected) {
238
+ throw new import_errors.SignatureError(
239
+ `Security verification failed: Recovered signer address (${normalizedSigner}) does not match expected user address (${normalizedExpected})`
240
+ );
241
+ }
242
+ }
243
+ const result = await routeSignedOperation(
244
+ sdk,
245
+ typedData,
246
+ signature,
247
+ options
248
+ );
249
+ return { type: "signed", hash: result.hash };
250
+ } else if (request.type === "direct") {
251
+ return await handleDirectOperation(sdk, request, options);
61
252
  }
62
- const result = await routeSignedOperation(sdk, typedData, signature);
63
- return {
64
- type: "signed",
65
- hash: result.hash
66
- };
253
+ throw new Error("Invalid request type for execution");
67
254
  }
68
- async function routeSignedOperation(sdk, typedData, signature) {
255
+ async function routeSignedOperation(sdk, typedData, signature, options) {
256
+ const validPrimaryTypes = [
257
+ "Permission",
258
+ "RevokePermission",
259
+ "TrustServer",
260
+ "AddServer",
261
+ "UntrustServer",
262
+ "ServerFilesAndPermission"
263
+ ];
264
+ if (!validPrimaryTypes.includes(typedData.primaryType)) {
265
+ throw new Error(
266
+ `Unsupported operation type: ${typedData.primaryType}. Supported types: ${validPrimaryTypes.join(", ")}`
267
+ );
268
+ }
69
269
  const primaryType = typedData.primaryType;
70
270
  switch (primaryType) {
71
271
  case "Permission":
@@ -74,7 +274,8 @@ async function routeSignedOperation(sdk, typedData, signature) {
74
274
  ...typedData,
75
275
  primaryType: "Permission"
76
276
  },
77
- signature
277
+ signature,
278
+ options
78
279
  );
79
280
  case "RevokePermission":
80
281
  return sdk.permissions.submitSignedRevoke(
@@ -82,7 +283,8 @@ async function routeSignedOperation(sdk, typedData, signature) {
82
283
  ...typedData,
83
284
  primaryType: "RevokePermission"
84
285
  },
85
- signature
286
+ signature,
287
+ options
86
288
  );
87
289
  case "TrustServer":
88
290
  return sdk.permissions.submitSignedTrustServer(
@@ -90,7 +292,8 @@ async function routeSignedOperation(sdk, typedData, signature) {
90
292
  ...typedData,
91
293
  primaryType: "TrustServer"
92
294
  },
93
- signature
295
+ signature,
296
+ options
94
297
  );
95
298
  case "AddServer":
96
299
  return sdk.permissions.submitSignedAddAndTrustServer(
@@ -98,7 +301,8 @@ async function routeSignedOperation(sdk, typedData, signature) {
98
301
  ...typedData,
99
302
  primaryType: "AddServer"
100
303
  },
101
- signature
304
+ signature,
305
+ options
102
306
  );
103
307
  case "UntrustServer":
104
308
  return sdk.permissions.submitSignedUntrustServer(
@@ -106,7 +310,8 @@ async function routeSignedOperation(sdk, typedData, signature) {
106
310
  ...typedData,
107
311
  primaryType: "UntrustServer"
108
312
  },
109
- signature
313
+ signature,
314
+ options
110
315
  );
111
316
  case "ServerFilesAndPermission":
112
317
  return sdk.permissions.submitSignedAddServerFilesAndPermissions(
@@ -114,97 +319,93 @@ async function routeSignedOperation(sdk, typedData, signature) {
114
319
  ...typedData,
115
320
  primaryType: "ServerFilesAndPermission"
116
321
  },
117
- signature
322
+ signature,
323
+ options
118
324
  );
119
- // RegisterGrantee is commented out as it's not supported by smart contracts yet
325
+ // TODO: RegisterGrantee with signature is not supported until
326
+ // DataPortabilityGrantees contract adds registerGranteeWithSignature function
120
327
  // case "RegisterGrantee":
121
328
  // return sdk.permissions.submitSignedRegisterGrantee(...);
122
329
  default:
123
- throw new Error(`Unsupported operation type: ${typedData.primaryType}`);
330
+ throw new Error(
331
+ `Unsupported operation type: ${typedData.primaryType}. Supported types: Permission, RevokePermission, TrustServer, AddServer, UntrustServer, ServerFilesAndPermission`
332
+ );
124
333
  }
125
334
  }
126
- async function handleDirectOperation(sdk, request) {
335
+ async function handleDirectOperation(sdk, request, options) {
127
336
  switch (request.operation) {
128
337
  case "submitFileAddition": {
129
338
  const { url, userAddress } = request.params;
130
339
  const result = await sdk.data.addFileWithPermissions(
131
340
  url,
132
341
  userAddress,
133
- []
342
+ [],
134
343
  // No permissions
344
+ options
135
345
  );
136
- const eventData = await sdk.waitForTransactionEvents(result);
137
- const fileId = eventData.expectedEvents?.FileAdded?.fileId;
138
- if (!fileId) {
139
- throw new Error("Failed to get fileId from transaction events");
140
- }
141
- return {
142
- type: "direct",
143
- result: {
144
- fileId: Number(fileId),
145
- transactionHash: result.hash
146
- }
147
- };
346
+ return { type: "direct", result };
148
347
  }
149
348
  case "submitFileAdditionWithPermissions": {
150
349
  const { url, userAddress, permissions } = request.params;
151
350
  const result = await sdk.data.addFileWithPermissions(
152
351
  url,
153
352
  userAddress,
154
- permissions
353
+ permissions,
354
+ options
155
355
  );
156
- const eventData = await sdk.waitForTransactionEvents(result);
157
- const fileId = eventData.expectedEvents?.FileAdded?.fileId;
158
- if (!fileId) {
159
- throw new Error("Failed to get fileId from transaction events");
160
- }
161
- return {
162
- type: "direct",
163
- result: {
164
- fileId: Number(fileId),
165
- transactionHash: result.hash
166
- }
167
- };
356
+ return { type: "direct", result };
168
357
  }
169
358
  case "submitFileAdditionComplete": {
170
359
  const { url, userAddress, permissions, schemaId, ownerAddress } = request.params;
171
- const sdkPermissions = permissions.map((p) => ({
172
- account: p.account,
173
- publicKey: p.key
174
- // Map 'key' to 'publicKey'
175
- }));
176
- const result = await sdk.data.addFileWithPermissionsAndSchema(
360
+ const txResult = await sdk.data.addFileWithEncryptedPermissionsAndSchema(
177
361
  url,
178
362
  ownerAddress ?? userAddress,
179
- sdkPermissions,
180
- schemaId
363
+ permissions,
364
+ // Already in correct format with encrypted 'key' field
365
+ schemaId,
366
+ options
181
367
  );
182
- const eventData = await sdk.waitForTransactionEvents(result);
183
- const fileId = eventData.expectedEvents?.FileAdded?.fileId;
184
- if (!fileId) {
185
- throw new Error("Failed to get fileId from transaction events");
368
+ const eventResult = await sdk.waitForTransactionEvents(txResult);
369
+ const fileAddedEvent = eventResult.expectedEvents?.FileAdded;
370
+ if (!fileAddedEvent || !fileAddedEvent.fileId) {
371
+ console.error("Event result:", eventResult);
372
+ throw new Error("FileAdded event not found in transaction");
186
373
  }
374
+ const fileId = Number(fileAddedEvent.fileId);
187
375
  return {
188
376
  type: "direct",
189
377
  result: {
190
- fileId: Number(fileId),
191
- transactionHash: result.hash
378
+ fileId,
379
+ transactionHash: txResult.hash
192
380
  }
193
381
  };
194
382
  }
195
383
  case "storeGrantFile": {
196
384
  const grantFile = request.params;
385
+ const dataController = sdk.data;
386
+ const context = dataController.context;
387
+ if (!context?.storageManager) {
388
+ throw new Error(
389
+ "Storage configuration is required for storing grant files"
390
+ );
391
+ }
197
392
  const blob = new Blob([JSON.stringify(grantFile)], {
198
393
  type: "application/json"
199
394
  });
200
- const result = await sdk.data.upload({
201
- content: blob,
202
- filename: `grant-${Date.now()}.json`
395
+ const uploadResult = await context.storageManager.upload(
396
+ blob,
397
+ `grant-${Date.now()}.json`
398
+ );
399
+ return { type: "direct", result: { url: uploadResult.url } };
400
+ }
401
+ case "submitRegisterGrantee": {
402
+ const { owner, granteeAddress, publicKey } = request.params;
403
+ const result = await sdk.permissions.submitRegisterGrantee({
404
+ owner,
405
+ granteeAddress,
406
+ publicKey
203
407
  });
204
- return {
205
- type: "direct",
206
- result: { url: result.url }
207
- };
408
+ return { type: "direct", result };
208
409
  }
209
410
  default: {
210
411
  const exhaustiveCheck = request;
@@ -214,7 +415,6 @@ async function handleDirectOperation(sdk, request) {
214
415
  }
215
416
  // Annotate the CommonJS export names for ESM import in node:
216
417
  0 && (module.exports = {
217
- handleRelayerOperation,
218
- handleRelayerRequest
418
+ handleRelayerOperation
219
419
  });
220
420
  //# sourceMappingURL=relayerHandler.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/relayerHandler.ts"],"sourcesContent":["import type { VanaInstance } from \"../index.node\";\nimport type {\n UnifiedRelayerRequest,\n UnifiedRelayerResponse,\n SignedRelayerRequest,\n DirectRelayerRequest,\n} from \"../types/relayer\";\nimport type {\n GenericTypedData,\n PermissionGrantTypedData,\n RevokePermissionTypedData,\n TrustServerTypedData,\n AddAndTrustServerTypedData,\n ServerFilesAndPermissionTypedData,\n TypedDataPrimaryType,\n} from \"../types/permissions\";\nimport { SignatureError } from \"../errors\";\nimport { recoverTypedDataAddress, getAddress, type Hash } from \"viem\";\n\n/**\n * Universal handler for all relayer operations.\n *\n * This function processes both EIP-712 signed operations and direct operations,\n * automatically routing to the appropriate SDK methods.\n *\n * @param sdk - Initialized Vana SDK instance\n * @param request - The unified relayer request\n * @returns Promise resolving to operation-specific response\n *\n * @category Server\n * @example\n * ```typescript\n * // In your server endpoint (Next.js example):\n * import { handleRelayerOperation } from '@opendatalabs/vana-sdk/node';\n *\n * export async function POST(request: NextRequest) {\n * try {\n * const body = await request.json();\n * const vana = getServerVanaInstance(); // Your server SDK instance\n *\n * const result = await handleRelayerOperation(vana, body);\n *\n * return NextResponse.json(result);\n * } catch (error) {\n * return NextResponse.json(\n * { error: error.message },\n * { status: 500 }\n * );\n * }\n * }\n * ```\n */\nexport async function handleRelayerOperation(\n sdk: VanaInstance,\n request: UnifiedRelayerRequest,\n): Promise<UnifiedRelayerResponse> {\n // Handle signed operations (EIP-712)\n if (request.type === \"signed\") {\n return handleSignedOperation(sdk, request);\n }\n\n // Handle direct operations (non-signed)\n return handleDirectOperation(sdk, request);\n}\n\n/**\n * Handle EIP-712 signed operations with full type safety\n */\nasync function handleSignedOperation(\n sdk: VanaInstance,\n request: SignedRelayerRequest,\n): Promise<UnifiedRelayerResponse> {\n const { typedData, signature, expectedUserAddress } = request;\n\n // Step 1: Verify the signature (security check)\n let recoveredAddress: `0x${string}`;\n try {\n recoveredAddress = await recoverTypedDataAddress({\n domain: {\n ...typedData.domain,\n chainId: typedData.domain.chainId\n ? BigInt(typedData.domain.chainId)\n : undefined,\n },\n types: typedData.types,\n primaryType: typedData.primaryType,\n message: typedData.message as unknown as Record<string, unknown>,\n signature,\n });\n } catch (error) {\n // Handle signature verification errors\n throw new SignatureError(\n `Signature verification failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Optional security check: Verify the signer matches expected address\n if (expectedUserAddress) {\n const normalizedExpected = getAddress(expectedUserAddress);\n const normalizedSigner = getAddress(recoveredAddress);\n\n if (normalizedSigner !== normalizedExpected) {\n throw new SignatureError(\n `Security verification failed: Recovered signer address (${normalizedSigner}) does not match expected user address (${normalizedExpected})`,\n );\n }\n }\n\n // Step 2: Route to appropriate SDK method based on primaryType\n // Using proper type narrowing instead of unsafe casts\n const result = await routeSignedOperation(sdk, typedData, signature);\n\n // Return the transaction hash with type\n return {\n type: \"signed\",\n hash: result.hash,\n };\n}\n\n/**\n * Route signed operations to the appropriate SDK method with type safety\n */\nasync function routeSignedOperation(\n sdk: VanaInstance,\n typedData: GenericTypedData,\n signature: Hash,\n) {\n const primaryType = typedData.primaryType as TypedDataPrimaryType;\n\n // Type-safe routing based on primaryType\n switch (primaryType) {\n case \"Permission\":\n // TypeScript knows this is a Permission operation\n return sdk.permissions.submitSignedGrant(\n {\n ...typedData,\n primaryType: \"Permission\",\n } as PermissionGrantTypedData,\n signature,\n );\n\n case \"RevokePermission\":\n return sdk.permissions.submitSignedRevoke(\n {\n ...typedData,\n primaryType: \"RevokePermission\",\n } as RevokePermissionTypedData,\n signature,\n );\n\n case \"TrustServer\":\n return sdk.permissions.submitSignedTrustServer(\n {\n ...typedData,\n primaryType: \"TrustServer\",\n } as TrustServerTypedData,\n signature,\n );\n\n case \"AddServer\":\n return sdk.permissions.submitSignedAddAndTrustServer(\n {\n ...typedData,\n primaryType: \"AddServer\",\n } as AddAndTrustServerTypedData,\n signature,\n );\n\n case \"UntrustServer\":\n return sdk.permissions.submitSignedUntrustServer(\n {\n ...typedData,\n primaryType: \"UntrustServer\",\n } as GenericTypedData,\n signature,\n );\n\n case \"ServerFilesAndPermission\":\n return sdk.permissions.submitSignedAddServerFilesAndPermissions(\n {\n ...typedData,\n primaryType: \"ServerFilesAndPermission\",\n } as ServerFilesAndPermissionTypedData,\n signature,\n );\n\n // RegisterGrantee is commented out as it's not supported by smart contracts yet\n // case \"RegisterGrantee\":\n // return sdk.permissions.submitSignedRegisterGrantee(...);\n\n default:\n throw new Error(`Unsupported operation type: ${typedData.primaryType}`);\n }\n}\n\n/**\n * Handle direct (non-signed) operations\n */\nasync function handleDirectOperation(\n sdk: VanaInstance,\n request: DirectRelayerRequest,\n): Promise<UnifiedRelayerResponse> {\n switch (request.operation) {\n case \"submitFileAddition\": {\n const { url, userAddress } = request.params;\n\n // Use SDK to add file with no permissions\n const result = await sdk.data.addFileWithPermissions(\n url,\n userAddress,\n [], // No permissions\n );\n\n // Wait for transaction events to get fileId\n const eventData = await sdk.waitForTransactionEvents(result);\n const fileId = eventData.expectedEvents?.FileAdded?.fileId;\n\n if (!fileId) {\n throw new Error(\"Failed to get fileId from transaction events\");\n }\n\n return {\n type: \"direct\",\n result: {\n fileId: Number(fileId),\n transactionHash: result.hash,\n },\n };\n }\n\n case \"submitFileAdditionWithPermissions\": {\n const { url, userAddress, permissions } = request.params;\n\n // Use SDK to add file with permissions\n const result = await sdk.data.addFileWithPermissions(\n url,\n userAddress,\n permissions,\n );\n\n // Wait for transaction events to get fileId\n const eventData = await sdk.waitForTransactionEvents(result);\n const fileId = eventData.expectedEvents?.FileAdded?.fileId;\n\n if (!fileId) {\n throw new Error(\"Failed to get fileId from transaction events\");\n }\n\n return {\n type: \"direct\",\n result: {\n fileId: Number(fileId),\n transactionHash: result.hash,\n },\n };\n }\n\n case \"submitFileAdditionComplete\": {\n const { url, userAddress, permissions, schemaId, ownerAddress } =\n request.params;\n\n // Map permissions from relayer format to SDK format\n const sdkPermissions = permissions.map((p) => ({\n account: p.account,\n publicKey: p.key, // Map 'key' to 'publicKey'\n }));\n\n // Use SDK to add file with permissions and schema\n const result = await sdk.data.addFileWithPermissionsAndSchema(\n url,\n ownerAddress ?? userAddress,\n sdkPermissions,\n schemaId,\n );\n\n // Wait for transaction events to get fileId\n const eventData = await sdk.waitForTransactionEvents(result);\n const fileId = eventData.expectedEvents?.FileAdded?.fileId;\n\n if (!fileId) {\n throw new Error(\"Failed to get fileId from transaction events\");\n }\n\n return {\n type: \"direct\",\n result: {\n fileId: Number(fileId),\n transactionHash: result.hash,\n },\n };\n }\n\n case \"storeGrantFile\": {\n const grantFile = request.params;\n\n // Store grant file using SDK's data controller\n // Convert grant file to blob for storage\n const blob = new Blob([JSON.stringify(grantFile)], {\n type: \"application/json\",\n });\n\n // Upload using the data controller\n const result = await sdk.data.upload({\n content: blob,\n filename: `grant-${Date.now()}.json`,\n });\n\n return {\n type: \"direct\",\n result: { url: result.url },\n };\n }\n\n default: {\n // TypeScript exhaustiveness check - ensures all cases are handled at compile time\n const exhaustiveCheck: never = request;\n // Return exhaustiveCheck to satisfy TypeScript while throwing an error\n // This should never be reached if all cases are handled\n return exhaustiveCheck;\n }\n }\n}\n\n// Legacy handler export - DEPRECATED\n// TODO: Remove in next major version\n// Migration guide: Use handleRelayerOperation instead\nexport { handleRelayerRequest } from \"./handler\";\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/server/relayerHandler.ts"],"sourcesContent":["import { v4 as uuidv4 } from \"uuid\";\nimport type { VanaInstance, VanaWithStores } from \"../index.node\";\nimport type {\n UnifiedRelayerRequest,\n UnifiedRelayerResponse,\n DirectRelayerRequest,\n} from \"../types/relayer\";\nimport type { TransactionResult } from \"../types\";\nimport type {\n TransactionOptions,\n TransactionReceipt,\n} from \"../types/operations\";\nimport type { OperationState } from \"../types/operationStore\";\nimport type { Contract, Fn } from \"../generated/event-types\";\nimport type {\n GenericTypedData,\n PermissionGrantTypedData,\n RevokePermissionTypedData,\n TrustServerTypedData,\n AddAndTrustServerTypedData,\n ServerFilesAndPermissionTypedData,\n TypedDataPrimaryType,\n} from \"../types/permissions\";\nimport { SignatureError } from \"../errors\";\nimport { recoverTypedDataAddress, getAddress, type Hash } from \"viem\";\n\n/**\n * Options for handleRelayerOperation\n */\nexport interface RelayerOperationOptions extends TransactionOptions {\n /**\n * Execution mode for the operation.\n *\n * @remarks\n * - 'sync' (default): Attempts to process the transaction immediately.\n * If a timeout occurs, automatically falls back to returning a pending operation ID.\n * This is the Vana App's current model.\n *\n * - 'async': Immediately queues the operation and returns a pending operation ID.\n * The transaction will be processed by a background worker.\n * Requires an operationStore to be configured.\n *\n * @default 'sync'\n */\n execution?: \"sync\" | \"async\";\n\n /**\n * Timeout for synchronous execution in milliseconds.\n * Only applies when execution is 'sync'.\n *\n * @default 30000 (30 seconds)\n */\n syncTimeout?: number;\n}\n\n/**\n * Universal handler for all relayer operations.\n *\n * This function processes both EIP-712 signed operations and direct operations,\n * automatically routing to the appropriate SDK methods.\n *\n * @param sdk - Initialized Vana SDK instance\n * @param request - The unified relayer request\n * @param options - Transaction and execution options\n * @returns Promise resolving to operation-specific response\n *\n * @category Server\n * @example\n * ```typescript\n * // In your server endpoint (Next.js example):\n * import { handleRelayerOperation } from '@opendatalabs/vana-sdk/node';\n *\n * export async function POST(request: NextRequest) {\n * try {\n * const body = await request.json();\n * const vana = getServerVanaInstance(); // Your server SDK instance\n *\n * // Explicit synchronous execution (Vana App model)\n * const result = await handleRelayerOperation(vana, body, {\n * execution: 'sync', // Explicit mode\n * syncTimeout: 45000 // 45 second timeout\n * });\n *\n * return NextResponse.json(result);\n * } catch (error) {\n * return NextResponse.json(\n * { error: error.message },\n * { status: 500 }\n * );\n * }\n * }\n * ```\n */\nexport async function handleRelayerOperation(\n sdk: VanaInstance,\n request: UnifiedRelayerRequest,\n options: RelayerOperationOptions = {},\n): Promise<UnifiedRelayerResponse> {\n // Type cast to access internal properties - safe for server-side relayer instances\n const sdkWithStores = sdk as VanaInstance & Partial<VanaWithStores>;\n const storeUntyped = sdkWithStores.operationStore;\n\n // Check if it's a IRelayerStateStore (has get/set methods)\n const isRelayerStore =\n storeUntyped && \"get\" in storeUntyped && \"set\" in storeUntyped;\n const store = isRelayerStore\n ? (storeUntyped as import(\"../types/operationStore\").IRelayerStateStore)\n : undefined;\n\n // Extract execution mode and timeout with defaults\n const executionMode = options.execution ?? \"sync\";\n const syncTimeout = options.syncTimeout ?? 30000; // 30 seconds default\n\n // Extract only TransactionOptions, excluding relayer-specific options\n // Pass undefined if no transaction options were provided\n const transactionOptions: TransactionOptions | undefined =\n options.gas ||\n options.gasPrice ||\n options.maxFeePerGas ||\n options.maxPriorityFeePerGas ||\n options.nonce !== undefined ||\n options.value ||\n options.signal ||\n options.onStatusUpdate\n ? {\n ...(options.gas && { gas: options.gas }),\n ...(options.gasPrice && { gasPrice: options.gasPrice }),\n ...(options.maxFeePerGas && { maxFeePerGas: options.maxFeePerGas }),\n ...(options.maxPriorityFeePerGas && {\n maxPriorityFeePerGas: options.maxPriorityFeePerGas,\n }),\n ...(options.nonce !== undefined && { nonce: options.nonce }),\n ...(options.value && { value: options.value }),\n ...(options.signal && { signal: options.signal }),\n ...(options.onStatusUpdate && {\n onStatusUpdate: options.onStatusUpdate,\n }),\n }\n : undefined;\n\n // --- STATEFUL (ROBUST) MODE ---\n // This block executes ONLY if the developer provided a relayer state store.\n if (store) {\n if (request.type === \"status_check\") {\n const state = await store.get(request.operationId);\n if (!state) return { type: \"error\", error: \"Operation not found\" };\n\n // If already confirmed or failed, return immediately\n if (state.status === \"confirmed\")\n return {\n type: \"confirmed\",\n hash: state.transactionHash,\n receipt: state.finalReceipt,\n };\n if (state.status === \"failed\")\n return { type: \"error\", error: state.error ?? \"Operation failed\" };\n\n // For pending operations, check the blockchain for transaction status\n if (state.status === \"pending\") {\n try {\n // Get a public client to check transaction status\n const publicClient = sdkWithStores.publicClient;\n\n if (publicClient) {\n // Check if transaction has been mined\n let receipt;\n try {\n receipt = await publicClient.getTransactionReceipt({\n hash: state.transactionHash,\n });\n } catch (receiptError: any) {\n // Transaction not found is expected - it may not be mined yet\n if (receiptError?.name !== \"TransactionReceiptNotFoundError\") {\n // Unexpected error - log but don't fail\n console.warn(\n `⚠️ [Relayer] Unexpected error checking receipt:`,\n receiptError?.message ?? receiptError,\n );\n }\n // Continue returning pending status\n receipt = null;\n }\n\n if (receipt) {\n // Update the operation state based on transaction status\n const updatedState: OperationState = {\n ...state,\n status: receipt.status === \"success\" ? \"confirmed\" : \"failed\",\n finalReceipt: receipt as TransactionReceipt,\n ...(receipt.status !== \"success\" && {\n error: \"Transaction reverted on chain\",\n }),\n };\n\n // Persist the updated state\n await store.set(request.operationId, updatedState);\n\n // Return the appropriate response\n if (receipt.status === \"success\") {\n return {\n type: \"confirmed\",\n hash: state.transactionHash,\n receipt: receipt as TransactionReceipt,\n };\n } else {\n return {\n type: \"error\",\n error: \"Transaction reverted on chain\",\n };\n }\n }\n } else {\n console.warn(\n \"⚠️ [Relayer] No public client available for status checking\",\n );\n }\n } catch (error) {\n console.error(\n `❌ [Relayer] Unexpected error in status check:`,\n error,\n );\n // Don't fail the operation, just continue returning pending\n }\n }\n\n return { type: \"pending\", operationId: request.operationId };\n }\n\n const operationId = uuidv4();\n\n // Handle async execution mode - immediately queue and return\n if (executionMode === \"async\") {\n // Store the operation for later processing\n await store.set(operationId, {\n status: \"pending\",\n transactionHash: \"\" as Hash, // Will be filled when processed\n originalRequest: request,\n nonce: options?.nonce,\n retryCount: 0,\n lastAttemptedGas: {\n maxFeePerGas: transactionOptions?.maxFeePerGas?.toString(),\n maxPriorityFeePerGas:\n transactionOptions?.maxPriorityFeePerGas?.toString(),\n },\n submittedAt: Date.now(),\n });\n\n console.log(\n `[Relayer] Operation ${operationId} queued for async processing`,\n );\n return { type: \"pending\", operationId };\n }\n\n // Handle sync execution mode (default) - try to execute immediately with timeout protection\n try {\n // Create a timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Sync execution timeout after ${syncTimeout}ms`));\n }, syncTimeout);\n });\n\n // Race between execution and timeout\n const response = await Promise.race([\n routeAndExecuteRequest(sdk, request, transactionOptions),\n timeoutPromise,\n ]);\n\n // Handle different response types\n if (response.type === \"signed\") {\n // Store signed transaction state\n await store.set(operationId, {\n status: \"confirmed\",\n transactionHash: response.hash,\n originalRequest: request,\n nonce: transactionOptions?.nonce,\n retryCount: 0,\n lastAttemptedGas: {\n maxFeePerGas: transactionOptions?.maxFeePerGas?.toString(),\n maxPriorityFeePerGas:\n transactionOptions?.maxPriorityFeePerGas?.toString(),\n },\n submittedAt: Date.now(),\n });\n\n // Return signed response as-is\n return response;\n } else if (response.type === \"direct\") {\n // Non-transactional direct operations - return as-is\n return response;\n } else {\n // Error responses - return as-is\n return response;\n }\n } catch (e) {\n // On timeout or error in sync mode, fall back to pending\n const error =\n e instanceof Error\n ? e\n : new Error(\"Unknown error during operation submission\");\n\n // Store as pending for recovery\n await store.set(operationId, {\n status: \"pending\",\n transactionHash: \"\" as Hash, // Will be filled when retried\n originalRequest: request,\n nonce: options?.nonce,\n retryCount: 0,\n lastAttemptedGas: {\n maxFeePerGas: transactionOptions?.maxFeePerGas?.toString(),\n maxPriorityFeePerGas:\n transactionOptions?.maxPriorityFeePerGas?.toString(),\n },\n submittedAt: Date.now(),\n error: error.message,\n });\n\n console.warn(\n `[Relayer] Sync execution failed/timed out, returning pending operationId: ${operationId}`,\n );\n return { type: \"pending\", operationId };\n }\n }\n\n // --- STATELESS (SIMPLE) MODE ---\n // This block executes if no IOperationStore was provided. Fire-and-forget.\n else {\n if (request.type === \"status_check\") {\n return {\n type: \"error\",\n error: \"Stateless relayer does not support operation status checks.\",\n };\n }\n\n try {\n const response = await routeAndExecuteRequest(\n sdk,\n request,\n transactionOptions,\n );\n\n // For stateless relayers, convert transaction responses to 'submitted' type\n if (response.type === \"signed\") {\n return { type: \"submitted\", hash: response.hash };\n } else if (\n response.type === \"direct\" &&\n response.result &&\n typeof response.result === \"object\" &&\n \"hash\" in response.result\n ) {\n // Direct operations that return TransactionResults\n return {\n type: \"submitted\",\n hash: (response.result as { hash: Hash }).hash,\n };\n } else {\n // Return other response types as-is (direct non-transaction results, error)\n return response;\n }\n } catch (e) {\n const error =\n e instanceof Error\n ? e\n : new Error(\"Unknown error during operation submission\");\n return { type: \"error\", error: error.message };\n }\n }\n}\n\n/**\n * Helper function to route and execute requests.\n * This simply delegates to the appropriate handler based on request type.\n */\nasync function routeAndExecuteRequest(\n sdk: VanaInstance,\n request: UnifiedRelayerRequest,\n options?: TransactionOptions,\n): Promise<UnifiedRelayerResponse> {\n if (request.type === \"signed\") {\n const { typedData, signature, expectedUserAddress } = request;\n\n // Step 1: Verify the signature (security check)\n let recoveredAddress: `0x${string}`;\n try {\n recoveredAddress = await recoverTypedDataAddress({\n domain: {\n ...typedData.domain,\n chainId: typedData.domain.chainId\n ? BigInt(typedData.domain.chainId)\n : undefined,\n },\n types: typedData.types,\n primaryType: typedData.primaryType,\n message: typedData.message as unknown as Record<string, unknown>,\n signature,\n });\n } catch (error) {\n // Handle signature verification errors\n throw new SignatureError(\n `Signature verification failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Optional security check: Verify the signer matches expected address\n if (expectedUserAddress) {\n const normalizedExpected = getAddress(expectedUserAddress);\n const normalizedSigner = getAddress(recoveredAddress);\n\n if (normalizedSigner !== normalizedExpected) {\n throw new SignatureError(\n `Security verification failed: Recovered signer address (${normalizedSigner}) does not match expected user address (${normalizedExpected})`,\n );\n }\n }\n\n // Step 2: Route to appropriate SDK method based on primaryType\n const result = await routeSignedOperation(\n sdk,\n typedData,\n signature,\n options,\n );\n return { type: \"signed\", hash: result.hash };\n } else if (request.type === \"direct\") {\n return await handleDirectOperation(sdk, request, options);\n }\n throw new Error(\"Invalid request type for execution\");\n}\n\n/**\n * Route signed operations to the appropriate SDK method with type safety.\n *\n * Returns a TransactionResult for one of the valid contracts and their functions.\n * Using Contract and Fn<Contract> ensures we're working with known contract types.\n */\nasync function routeSignedOperation(\n sdk: VanaInstance,\n typedData: GenericTypedData,\n signature: Hash,\n options?: TransactionOptions,\n): Promise<TransactionResult<Contract, Fn<Contract>>> {\n // Validate primaryType before casting\n const validPrimaryTypes: readonly TypedDataPrimaryType[] = [\n \"Permission\",\n \"RevokePermission\",\n \"TrustServer\",\n \"AddServer\",\n \"UntrustServer\",\n \"ServerFilesAndPermission\",\n ] as const;\n\n if (\n !validPrimaryTypes.includes(typedData.primaryType as TypedDataPrimaryType)\n ) {\n throw new Error(\n `Unsupported operation type: ${typedData.primaryType}. ` +\n `Supported types: ${validPrimaryTypes.join(\", \")}`,\n );\n }\n const primaryType = typedData.primaryType as TypedDataPrimaryType;\n\n // Type-safe routing based on primaryType\n switch (primaryType) {\n case \"Permission\":\n // TypeScript knows this is a Permission operation\n return sdk.permissions.submitSignedGrant(\n {\n ...typedData,\n primaryType: \"Permission\",\n } as PermissionGrantTypedData,\n signature,\n options,\n );\n\n case \"RevokePermission\":\n return sdk.permissions.submitSignedRevoke(\n {\n ...typedData,\n primaryType: \"RevokePermission\",\n } as RevokePermissionTypedData,\n signature,\n options,\n );\n\n case \"TrustServer\":\n // Note: TrustServer operation is deprecated but still supported for backwards compatibility\n // New implementations should use AddServer (AddAndTrustServer) instead\n return sdk.permissions.submitSignedTrustServer(\n {\n ...typedData,\n primaryType: \"TrustServer\",\n } as TrustServerTypedData,\n signature,\n options,\n );\n\n case \"AddServer\":\n return sdk.permissions.submitSignedAddAndTrustServer(\n {\n ...typedData,\n primaryType: \"AddServer\",\n } as AddAndTrustServerTypedData,\n signature,\n options,\n );\n\n case \"UntrustServer\":\n return sdk.permissions.submitSignedUntrustServer(\n {\n ...typedData,\n primaryType: \"UntrustServer\",\n } as GenericTypedData,\n signature,\n options,\n );\n\n case \"ServerFilesAndPermission\":\n return sdk.permissions.submitSignedAddServerFilesAndPermissions(\n {\n ...typedData,\n primaryType: \"ServerFilesAndPermission\",\n } as ServerFilesAndPermissionTypedData,\n signature,\n options,\n );\n\n // TODO: RegisterGrantee with signature is not supported until\n // DataPortabilityGrantees contract adds registerGranteeWithSignature function\n // case \"RegisterGrantee\":\n // return sdk.permissions.submitSignedRegisterGrantee(...);\n\n default:\n // This should never be reached due to validation above, but TypeScript requires it\n throw new Error(\n `Unsupported operation type: ${typedData.primaryType}. ` +\n `Supported types: Permission, RevokePermission, TrustServer, AddServer, UntrustServer, ServerFilesAndPermission`,\n );\n }\n}\n\n/**\n * Handle direct (non-signed) operations\n */\nasync function handleDirectOperation(\n sdk: VanaInstance,\n request: DirectRelayerRequest,\n options?: TransactionOptions,\n): Promise<UnifiedRelayerResponse> {\n switch (request.operation) {\n case \"submitFileAddition\": {\n const { url, userAddress } = request.params;\n\n // Use SDK to add file with no permissions\n const result = await sdk.data.addFileWithPermissions(\n url,\n userAddress,\n [], // No permissions\n options,\n );\n\n // Return as direct result wrapped in UnifiedRelayerResponse\n return { type: \"direct\", result };\n }\n\n case \"submitFileAdditionWithPermissions\": {\n const { url, userAddress, permissions } = request.params;\n\n // Use SDK to add file with permissions\n const result = await sdk.data.addFileWithPermissions(\n url,\n userAddress,\n permissions,\n options,\n );\n\n // Return as direct result wrapped in UnifiedRelayerResponse\n return { type: \"direct\", result };\n }\n\n case \"submitFileAdditionComplete\": {\n const { url, userAddress, permissions, schemaId, ownerAddress } =\n request.params;\n\n // Permissions are already encrypted, use the appropriate method\n // No mapping needed - permissions already have { account, key } format\n const txResult = await sdk.data.addFileWithEncryptedPermissionsAndSchema(\n url,\n ownerAddress ?? userAddress,\n permissions, // Already in correct format with encrypted 'key' field\n schemaId,\n options,\n );\n\n // File uploads need synchronous response with fileId\n // Use the SDK's built-in event parsing - it knows how to extract events from TransactionResult\n const eventResult = await sdk.waitForTransactionEvents(txResult);\n const fileAddedEvent = eventResult.expectedEvents?.FileAdded;\n\n if (!fileAddedEvent || !fileAddedEvent.fileId) {\n console.error(\"Event result:\", eventResult);\n throw new Error(\"FileAdded event not found in transaction\");\n }\n\n const fileId = Number(fileAddedEvent.fileId);\n\n // Return as a direct result wrapped in UnifiedRelayerResponse\n return {\n type: \"direct\",\n result: {\n fileId,\n transactionHash: txResult.hash,\n },\n };\n }\n\n case \"storeGrantFile\": {\n const grantFile = request.params;\n\n // Access the data controller's context which has storage\n const dataController = sdk.data as any;\n const context = dataController.context;\n\n if (!context?.storageManager) {\n throw new Error(\n \"Storage configuration is required for storing grant files\",\n );\n }\n\n // Convert grant file to blob for storage\n const blob = new Blob([JSON.stringify(grantFile)], {\n type: \"application/json\",\n });\n\n // Upload directly to storage (IPFS) without blockchain transaction\n const uploadResult = await context.storageManager.upload(\n blob,\n `grant-${Date.now()}.json`,\n );\n\n return { type: \"direct\", result: { url: uploadResult.url } };\n }\n\n case \"submitRegisterGrantee\": {\n const { owner, granteeAddress, publicKey } = request.params;\n\n // Use SDK to register grantee\n const result = await sdk.permissions.submitRegisterGrantee({\n owner,\n granteeAddress,\n publicKey,\n });\n\n // Return as direct result wrapped in UnifiedRelayerResponse\n return { type: \"direct\", result };\n }\n\n default: {\n // TypeScript exhaustiveness check - ensures all cases are handled at compile time\n const exhaustiveCheck: never = request;\n // Return exhaustiveCheck to satisfy TypeScript while throwing an error\n // This should never be reached if all cases are handled\n return exhaustiveCheck;\n }\n }\n}\n"],"mappings":"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","names":["uuidv4"]}
@@ -1,5 +1,33 @@
1
1
  import type { VanaInstance } from "../index.node";
2
2
  import type { UnifiedRelayerRequest, UnifiedRelayerResponse } from "../types/relayer";
3
+ import type { TransactionOptions } from "../types/operations";
4
+ /**
5
+ * Options for handleRelayerOperation
6
+ */
7
+ export interface RelayerOperationOptions extends TransactionOptions {
8
+ /**
9
+ * Execution mode for the operation.
10
+ *
11
+ * @remarks
12
+ * - 'sync' (default): Attempts to process the transaction immediately.
13
+ * If a timeout occurs, automatically falls back to returning a pending operation ID.
14
+ * This is the Vana App's current model.
15
+ *
16
+ * - 'async': Immediately queues the operation and returns a pending operation ID.
17
+ * The transaction will be processed by a background worker.
18
+ * Requires an operationStore to be configured.
19
+ *
20
+ * @default 'sync'
21
+ */
22
+ execution?: "sync" | "async";
23
+ /**
24
+ * Timeout for synchronous execution in milliseconds.
25
+ * Only applies when execution is 'sync'.
26
+ *
27
+ * @default 30000 (30 seconds)
28
+ */
29
+ syncTimeout?: number;
30
+ }
3
31
  /**
4
32
  * Universal handler for all relayer operations.
5
33
  *
@@ -8,6 +36,7 @@ import type { UnifiedRelayerRequest, UnifiedRelayerResponse } from "../types/rel
8
36
  *
9
37
  * @param sdk - Initialized Vana SDK instance
10
38
  * @param request - The unified relayer request
39
+ * @param options - Transaction and execution options
11
40
  * @returns Promise resolving to operation-specific response
12
41
  *
13
42
  * @category Server
@@ -21,7 +50,11 @@ import type { UnifiedRelayerRequest, UnifiedRelayerResponse } from "../types/rel
21
50
  * const body = await request.json();
22
51
  * const vana = getServerVanaInstance(); // Your server SDK instance
23
52
  *
24
- * const result = await handleRelayerOperation(vana, body);
53
+ * // Explicit synchronous execution (Vana App model)
54
+ * const result = await handleRelayerOperation(vana, body, {
55
+ * execution: 'sync', // Explicit mode
56
+ * syncTimeout: 45000 // 45 second timeout
57
+ * });
25
58
  *
26
59
  * return NextResponse.json(result);
27
60
  * } catch (error) {
@@ -33,5 +66,4 @@ import type { UnifiedRelayerRequest, UnifiedRelayerResponse } from "../types/rel
33
66
  * }
34
67
  * ```
35
68
  */
36
- export declare function handleRelayerOperation(sdk: VanaInstance, request: UnifiedRelayerRequest): Promise<UnifiedRelayerResponse>;
37
- export { handleRelayerRequest } from "./handler";
69
+ export declare function handleRelayerOperation(sdk: VanaInstance, request: UnifiedRelayerRequest, options?: RelayerOperationOptions): Promise<UnifiedRelayerResponse>;