@gelatocloud/gasless 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/_dist/account/actions/getFeeQuote.d.ts +11 -0
  2. package/_dist/account/actions/getFeeQuote.d.ts.map +1 -0
  3. package/_dist/account/actions/getFeeQuote.js +21 -0
  4. package/_dist/account/actions/getFeeQuote.js.map +1 -0
  5. package/_dist/account/actions/index.d.ts +4 -0
  6. package/_dist/account/actions/index.d.ts.map +1 -0
  7. package/_dist/account/actions/index.js +20 -0
  8. package/_dist/account/actions/index.js.map +1 -0
  9. package/_dist/account/actions/sendTransaction.d.ts +20 -0
  10. package/_dist/account/actions/sendTransaction.d.ts.map +1 -0
  11. package/_dist/account/actions/sendTransaction.js +33 -0
  12. package/_dist/account/actions/sendTransaction.js.map +1 -0
  13. package/_dist/account/actions/sendTransactionSync.d.ts +9 -0
  14. package/_dist/account/actions/sendTransactionSync.d.ts.map +1 -0
  15. package/_dist/account/actions/sendTransactionSync.js +34 -0
  16. package/_dist/account/actions/sendTransactionSync.js.map +1 -0
  17. package/_dist/account/adapters/gelato/abi.d.ts +39 -0
  18. package/_dist/account/adapters/gelato/abi.d.ts.map +1 -0
  19. package/_dist/account/adapters/gelato/abi.js +13 -0
  20. package/_dist/account/adapters/gelato/abi.js.map +1 -0
  21. package/_dist/account/adapters/gelato/constants.d.ts +7 -0
  22. package/_dist/account/adapters/gelato/constants.d.ts.map +1 -0
  23. package/_dist/account/adapters/gelato/constants.js +9 -0
  24. package/_dist/account/adapters/gelato/constants.js.map +1 -0
  25. package/_dist/account/adapters/gelato/index.d.ts +10 -0
  26. package/_dist/account/adapters/gelato/index.d.ts.map +1 -0
  27. package/_dist/account/adapters/gelato/index.js +160 -0
  28. package/_dist/account/adapters/gelato/index.js.map +1 -0
  29. package/_dist/account/adapters/index.d.ts +2 -0
  30. package/_dist/account/adapters/index.d.ts.map +1 -0
  31. package/_dist/account/adapters/index.js +18 -0
  32. package/_dist/account/adapters/index.js.map +1 -0
  33. package/_dist/account/adapters/types/index.d.ts +22 -0
  34. package/_dist/account/adapters/types/index.d.ts.map +1 -0
  35. package/_dist/account/adapters/types/index.js +3 -0
  36. package/_dist/account/adapters/types/index.js.map +1 -0
  37. package/_dist/account/index.d.ts +17 -0
  38. package/_dist/account/index.d.ts.map +1 -0
  39. package/_dist/account/index.js +41 -0
  40. package/_dist/account/index.js.map +1 -0
  41. package/_dist/account/utils/delegation.d.ts +4 -0
  42. package/_dist/account/utils/delegation.d.ts.map +1 -0
  43. package/_dist/account/utils/delegation.js +12 -0
  44. package/_dist/account/utils/delegation.js.map +1 -0
  45. package/_dist/account/utils/estimation.d.ts +3 -0
  46. package/_dist/account/utils/estimation.d.ts.map +1 -0
  47. package/_dist/account/utils/estimation.js +19 -0
  48. package/_dist/account/utils/estimation.js.map +1 -0
  49. package/_dist/account/utils/index.d.ts +3 -0
  50. package/_dist/account/utils/index.d.ts.map +1 -0
  51. package/_dist/account/utils/index.js +19 -0
  52. package/_dist/account/utils/index.js.map +1 -0
  53. package/_dist/bundler/actions/estimateUserOperationGas.d.ts +6 -0
  54. package/_dist/bundler/actions/estimateUserOperationGas.d.ts.map +1 -0
  55. package/_dist/bundler/actions/estimateUserOperationGas.js +43 -0
  56. package/_dist/bundler/actions/estimateUserOperationGas.js.map +1 -0
  57. package/_dist/bundler/actions/getUserOperationGasPrice.d.ts +5 -0
  58. package/_dist/bundler/actions/getUserOperationGasPrice.d.ts.map +1 -0
  59. package/_dist/bundler/actions/getUserOperationGasPrice.js +20 -0
  60. package/_dist/bundler/actions/getUserOperationGasPrice.js.map +1 -0
  61. package/_dist/bundler/actions/getUserOperationQuote.d.ts +13 -0
  62. package/_dist/bundler/actions/getUserOperationQuote.d.ts.map +1 -0
  63. package/_dist/bundler/actions/getUserOperationQuote.js +50 -0
  64. package/_dist/bundler/actions/getUserOperationQuote.js.map +1 -0
  65. package/_dist/bundler/actions/index.d.ts +7 -0
  66. package/_dist/bundler/actions/index.d.ts.map +1 -0
  67. package/_dist/bundler/actions/index.js +23 -0
  68. package/_dist/bundler/actions/index.js.map +1 -0
  69. package/_dist/bundler/actions/prepareUserOperation.d.ts +6 -0
  70. package/_dist/bundler/actions/prepareUserOperation.d.ts.map +1 -0
  71. package/_dist/bundler/actions/prepareUserOperation.js +340 -0
  72. package/_dist/bundler/actions/prepareUserOperation.js.map +1 -0
  73. package/_dist/bundler/actions/sendUserOperation.d.ts +6 -0
  74. package/_dist/bundler/actions/sendUserOperation.d.ts.map +1 -0
  75. package/_dist/bundler/actions/sendUserOperation.js +41 -0
  76. package/_dist/bundler/actions/sendUserOperation.js.map +1 -0
  77. package/_dist/bundler/actions/sendUserOperationSync.d.ts +9 -0
  78. package/_dist/bundler/actions/sendUserOperationSync.d.ts.map +1 -0
  79. package/_dist/bundler/actions/sendUserOperationSync.js +42 -0
  80. package/_dist/bundler/actions/sendUserOperationSync.js.map +1 -0
  81. package/_dist/bundler/index.d.ts +18 -0
  82. package/_dist/bundler/index.d.ts.map +1 -0
  83. package/_dist/bundler/index.js +61 -0
  84. package/_dist/bundler/index.js.map +1 -0
  85. package/_dist/index.d.ts +5 -0
  86. package/_dist/index.d.ts.map +1 -0
  87. package/_dist/index.js +21 -0
  88. package/_dist/index.js.map +1 -0
  89. package/_dist/relayer/constants/index.d.ts +3 -0
  90. package/_dist/relayer/constants/index.d.ts.map +1 -0
  91. package/_dist/relayer/constants/index.js +6 -0
  92. package/_dist/relayer/constants/index.js.map +1 -0
  93. package/_dist/relayer/evm/actions/getCapabilities.d.ts +21 -0
  94. package/_dist/relayer/evm/actions/getCapabilities.d.ts.map +1 -0
  95. package/_dist/relayer/evm/actions/getCapabilities.js +19 -0
  96. package/_dist/relayer/evm/actions/getCapabilities.js.map +1 -0
  97. package/_dist/relayer/evm/actions/getFeeData.d.ts +21 -0
  98. package/_dist/relayer/evm/actions/getFeeData.d.ts.map +1 -0
  99. package/_dist/relayer/evm/actions/getFeeData.js +26 -0
  100. package/_dist/relayer/evm/actions/getFeeData.js.map +1 -0
  101. package/_dist/relayer/evm/actions/getFeeQuote.d.ts +22 -0
  102. package/_dist/relayer/evm/actions/getFeeQuote.d.ts.map +1 -0
  103. package/_dist/relayer/evm/actions/getFeeQuote.js +27 -0
  104. package/_dist/relayer/evm/actions/getFeeQuote.js.map +1 -0
  105. package/_dist/relayer/evm/actions/getStatus.d.ts +81 -0
  106. package/_dist/relayer/evm/actions/getStatus.d.ts.map +1 -0
  107. package/_dist/relayer/evm/actions/getStatus.js +72 -0
  108. package/_dist/relayer/evm/actions/getStatus.js.map +1 -0
  109. package/_dist/relayer/evm/actions/index.d.ts +8 -0
  110. package/_dist/relayer/evm/actions/index.d.ts.map +1 -0
  111. package/_dist/relayer/evm/actions/index.js +24 -0
  112. package/_dist/relayer/evm/actions/index.js.map +1 -0
  113. package/_dist/relayer/evm/actions/sendTransaction.d.ts +12 -0
  114. package/_dist/relayer/evm/actions/sendTransaction.d.ts.map +1 -0
  115. package/_dist/relayer/evm/actions/sendTransaction.js +22 -0
  116. package/_dist/relayer/evm/actions/sendTransaction.js.map +1 -0
  117. package/_dist/relayer/evm/actions/sendTransactionSync.d.ts +8 -0
  118. package/_dist/relayer/evm/actions/sendTransactionSync.d.ts.map +1 -0
  119. package/_dist/relayer/evm/actions/sendTransactionSync.js +23 -0
  120. package/_dist/relayer/evm/actions/sendTransactionSync.js.map +1 -0
  121. package/_dist/relayer/evm/actions/waitForStatus.d.ts +4 -0
  122. package/_dist/relayer/evm/actions/waitForStatus.d.ts.map +1 -0
  123. package/_dist/relayer/evm/actions/waitForStatus.js +17 -0
  124. package/_dist/relayer/evm/actions/waitForStatus.js.map +1 -0
  125. package/_dist/relayer/evm/index.d.ts +18 -0
  126. package/_dist/relayer/evm/index.d.ts.map +1 -0
  127. package/_dist/relayer/evm/index.js +46 -0
  128. package/_dist/relayer/evm/index.js.map +1 -0
  129. package/_dist/relayer/index.d.ts +2 -0
  130. package/_dist/relayer/index.d.ts.map +1 -0
  131. package/_dist/relayer/index.js +18 -0
  132. package/_dist/relayer/index.js.map +1 -0
  133. package/_dist/tsconfig.build.tsbuildinfo +1 -0
  134. package/_dist/types/error.d.ts +14 -0
  135. package/_dist/types/error.d.ts.map +1 -0
  136. package/_dist/types/error.js +27 -0
  137. package/_dist/types/error.js.map +1 -0
  138. package/_dist/types/index.d.ts +4 -0
  139. package/_dist/types/index.d.ts.map +1 -0
  140. package/_dist/types/index.js +20 -0
  141. package/_dist/types/index.js.map +1 -0
  142. package/_dist/types/payment.d.ts +17 -0
  143. package/_dist/types/payment.d.ts.map +1 -0
  144. package/_dist/types/payment.js +16 -0
  145. package/_dist/types/payment.js.map +1 -0
  146. package/_dist/types/schema.d.ts +10 -0
  147. package/_dist/types/schema.d.ts.map +1 -0
  148. package/_dist/types/schema.js +25 -0
  149. package/_dist/types/schema.js.map +1 -0
  150. package/_dist/utils/index.d.ts +3 -0
  151. package/_dist/utils/index.d.ts.map +1 -0
  152. package/_dist/utils/index.js +19 -0
  153. package/_dist/utils/index.js.map +1 -0
  154. package/_dist/utils/payment.d.ts +3 -0
  155. package/_dist/utils/payment.d.ts.map +1 -0
  156. package/_dist/utils/payment.js +17 -0
  157. package/_dist/utils/payment.js.map +1 -0
  158. package/_dist/utils/serialize.d.ts +17 -0
  159. package/_dist/utils/serialize.d.ts.map +1 -0
  160. package/_dist/utils/serialize.js +77 -0
  161. package/_dist/utils/serialize.js.map +1 -0
  162. package/account/actions/getFeeQuote.ts +34 -0
  163. package/account/actions/index.ts +3 -0
  164. package/account/actions/sendTransaction.ts +61 -0
  165. package/account/actions/sendTransactionSync.ts +51 -0
  166. package/account/adapters/gelato/abi.ts +13 -0
  167. package/account/adapters/gelato/constants.ts +13 -0
  168. package/account/adapters/gelato/index.ts +216 -0
  169. package/account/adapters/index.ts +1 -0
  170. package/account/adapters/types/index.ts +36 -0
  171. package/account/index.ts +60 -0
  172. package/account/utils/delegation.ts +9 -0
  173. package/account/utils/estimation.ts +29 -0
  174. package/account/utils/index.ts +2 -0
  175. package/bundler/actions/estimateUserOperationGas.ts +63 -0
  176. package/bundler/actions/getUserOperationGasPrice.ts +25 -0
  177. package/bundler/actions/getUserOperationQuote.ts +83 -0
  178. package/bundler/actions/index.ts +6 -0
  179. package/bundler/actions/prepareUserOperation.ts +437 -0
  180. package/bundler/actions/sendUserOperation.ts +64 -0
  181. package/bundler/actions/sendUserOperationSync.ts +71 -0
  182. package/bundler/index.ts +98 -0
  183. package/index.ts +4 -0
  184. package/package.json +36 -0
  185. package/relayer/constants/index.ts +2 -0
  186. package/relayer/evm/actions/getCapabilities.ts +22 -0
  187. package/relayer/evm/actions/getFeeData.ts +36 -0
  188. package/relayer/evm/actions/getFeeQuote.ts +39 -0
  189. package/relayer/evm/actions/getStatus.ts +92 -0
  190. package/relayer/evm/actions/index.ts +7 -0
  191. package/relayer/evm/actions/sendTransaction.ts +33 -0
  192. package/relayer/evm/actions/sendTransactionSync.ts +30 -0
  193. package/relayer/evm/actions/waitForStatus.ts +24 -0
  194. package/relayer/evm/index.ts +68 -0
  195. package/relayer/index.ts +1 -0
  196. package/tsconfig.build.json +19 -0
  197. package/tsconfig.json +8 -0
  198. package/types/error.ts +38 -0
  199. package/types/index.ts +3 -0
  200. package/types/payment.ts +23 -0
  201. package/types/schema.ts +28 -0
  202. package/utils/index.ts +2 -0
  203. package/utils/payment.ts +20 -0
  204. package/utils/serialize.ts +91 -0
@@ -0,0 +1,437 @@
1
+ import type { Call, Chain, Client, SignedAuthorization, Transport } from 'viem';
2
+ import {
3
+ type EstimateUserOperationGasParameters,
4
+ getPaymasterData as getPaymasterData_,
5
+ getPaymasterStubData as getPaymasterStubData_,
6
+ type PrepareUserOperationParameters,
7
+ type PrepareUserOperationRequest,
8
+ type PrepareUserOperationReturnType,
9
+ type SmartAccount,
10
+ type UserOperation
11
+ } from 'viem/account-abstraction';
12
+ import { parseAccount } from 'viem/accounts';
13
+ import { getChainId as getChainId_, prepareAuthorization } from 'viem/actions';
14
+ import { concat, encodeFunctionData, getAction } from 'viem/utils';
15
+ import type { CapabilitiesByChain } from '../../relayer/evm/actions/index.js';
16
+ import { AccountNotFoundError, type Payment, PaymentType } from '../../types/index.js';
17
+ import { appendPayment } from '../../utils/payment.js';
18
+ import type { GelatoBundlerClient } from '..';
19
+ import { estimateUserOperationGas } from './estimateUserOperationGas.js';
20
+ import { getUserOperationGasPrice } from './getUserOperationGasPrice.js';
21
+ import { getUserOperationQuote } from './getUserOperationQuote.js';
22
+
23
+ const defaultParameters = [
24
+ 'factory',
25
+ 'fees',
26
+ 'gas',
27
+ 'paymaster',
28
+ 'nonce',
29
+ 'signature',
30
+ 'authorization'
31
+ ] as const;
32
+
33
+ export const prepareUserOperation = async <
34
+ account extends SmartAccount | undefined,
35
+ const calls extends readonly unknown[],
36
+ const request extends PrepareUserOperationRequest<account, accountOverride, calls>,
37
+ accountOverride extends SmartAccount | undefined = undefined
38
+ >(
39
+ client: Client<Transport, Chain | undefined, account>,
40
+ parameters_: PrepareUserOperationParameters<account, accountOverride, calls, request>,
41
+ capabilities: CapabilitiesByChain,
42
+ payment?: Payment,
43
+ quote: boolean = false
44
+ ): Promise<PrepareUserOperationReturnType<account, accountOverride, calls, request>> => {
45
+ const parameters = parameters_ as PrepareUserOperationParameters;
46
+ const {
47
+ account: account_ = client.account,
48
+ parameters: properties = defaultParameters,
49
+ stateOverride
50
+ } = parameters;
51
+
52
+ ////////////////////////////////////////////////////////////////////////////////
53
+ // Assert that an Account is defined.
54
+ ////////////////////////////////////////////////////////////////////////////////
55
+
56
+ if (!account_) throw new AccountNotFoundError();
57
+ const account = parseAccount(account_);
58
+
59
+ ////////////////////////////////////////////////////////////////////////////////
60
+ // Declare typed Bundler Client.
61
+ ////////////////////////////////////////////////////////////////////////////////
62
+
63
+ const bundlerClient = client as unknown as GelatoBundlerClient;
64
+
65
+ ////////////////////////////////////////////////////////////////////////////////
66
+ // Declare Paymaster properties.
67
+ ////////////////////////////////////////////////////////////////////////////////
68
+
69
+ const paymaster = parameters.paymaster ?? bundlerClient?.paymaster;
70
+ const paymasterAddress = typeof paymaster === 'string' ? paymaster : undefined;
71
+ const { getPaymasterStubData, getPaymasterData } = (() => {
72
+ // If `paymaster: true`, we will assume the Bundler Client supports Paymaster Actions.
73
+ if (paymaster === true)
74
+ return {
75
+ // biome-ignore lint/suspicious/noExplicitAny: copied from viem
76
+ getPaymasterData: (parameters: any) =>
77
+ getAction(bundlerClient, getPaymasterData_, 'getPaymasterData')(parameters),
78
+ // biome-ignore lint/suspicious/noExplicitAny: copied from viem
79
+ getPaymasterStubData: (parameters: any) =>
80
+ getAction(bundlerClient, getPaymasterStubData_, 'getPaymasterStubData')(parameters)
81
+ };
82
+
83
+ // If Actions are passed to `paymaster` (via Paymaster Client or directly), we will use them.
84
+ if (typeof paymaster === 'object') {
85
+ const { getPaymasterStubData, getPaymasterData } = paymaster;
86
+ return {
87
+ getPaymasterData: getPaymasterData && getPaymasterStubData ? getPaymasterData : undefined,
88
+ getPaymasterStubData: (getPaymasterData && getPaymasterStubData
89
+ ? getPaymasterStubData
90
+ : getPaymasterData) as typeof getPaymasterStubData
91
+ };
92
+ }
93
+
94
+ // No Paymaster functions.
95
+ return {
96
+ getPaymasterData: undefined,
97
+ getPaymasterStubData: undefined
98
+ };
99
+ })();
100
+ const paymasterContext = parameters.paymasterContext
101
+ ? parameters.paymasterContext
102
+ : bundlerClient?.paymasterContext;
103
+
104
+ ////////////////////////////////////////////////////////////////////////////////
105
+ // Set up the User Operation request.
106
+ ////////////////////////////////////////////////////////////////////////////////
107
+
108
+ let request = {
109
+ ...parameters,
110
+ paymaster: paymasterAddress,
111
+ sender: account.address
112
+ } as PrepareUserOperationRequest;
113
+
114
+ ////////////////////////////////////////////////////////////////////////////////
115
+ // Concurrently prepare properties required to fill the User Operation.
116
+ ////////////////////////////////////////////////////////////////////////////////
117
+
118
+ const [{ callsWithoutPayment, callData }, factory, fees, nonce, authorization] =
119
+ await Promise.all([
120
+ (async () => {
121
+ if (parameters.calls) {
122
+ const callsWithoutPayment = parameters.calls.map((call_) => {
123
+ const call = call_ as Call;
124
+ if (call.abi)
125
+ return {
126
+ data: encodeFunctionData(call),
127
+ to: call.to,
128
+ value: call.value
129
+ } as Call;
130
+ return call as Call;
131
+ });
132
+
133
+ const calls =
134
+ payment?.type === PaymentType.Token
135
+ ? appendPayment(callsWithoutPayment, payment.address, capabilities.feeCollector, 1n)
136
+ : callsWithoutPayment;
137
+
138
+ const callData = await account.encodeCalls(calls);
139
+
140
+ return {
141
+ callData,
142
+ callsWithoutPayment
143
+ };
144
+ }
145
+
146
+ if (payment?.type !== PaymentType.Token) {
147
+ return {
148
+ callData: parameters.callData,
149
+ callsWithoutPayment: undefined
150
+ };
151
+ }
152
+
153
+ if (!account.decodeCalls) {
154
+ throw new Error(
155
+ 'Account must be able to decodeCalls in order to append token payments if raw callData is specified'
156
+ );
157
+ }
158
+
159
+ const callsWithoutPayment = (await account.decodeCalls(parameters.callData)) as Call[];
160
+
161
+ const calls = appendPayment(
162
+ callsWithoutPayment,
163
+ payment.address,
164
+ capabilities.feeCollector,
165
+ 1n
166
+ );
167
+
168
+ const callData = await account.encodeCalls(calls);
169
+
170
+ return {
171
+ callData,
172
+ callsWithoutPayment
173
+ };
174
+ })(),
175
+ (async () => {
176
+ if (!properties.includes('factory')) return undefined;
177
+ if (parameters.initCode) return { initCode: parameters.initCode };
178
+ if (parameters.factory && parameters.factoryData) {
179
+ return {
180
+ factory: parameters.factory,
181
+ factoryData: parameters.factoryData
182
+ };
183
+ }
184
+
185
+ const { factory, factoryData } = await account.getFactoryArgs();
186
+
187
+ if (account.entryPoint.version === '0.6')
188
+ return {
189
+ initCode: factory && factoryData ? concat([factory, factoryData]) : undefined
190
+ };
191
+ return {
192
+ factory,
193
+ factoryData
194
+ };
195
+ })(),
196
+ (async () => {
197
+ if (!properties.includes('fees')) return undefined;
198
+
199
+ // If we have sufficient properties for fees, return them.
200
+ if (
201
+ typeof parameters.maxFeePerGas === 'bigint' &&
202
+ typeof parameters.maxPriorityFeePerGas === 'bigint'
203
+ )
204
+ return request;
205
+
206
+ const fees = await getUserOperationGasPrice(bundlerClient, payment);
207
+
208
+ return {
209
+ ...request,
210
+ ...fees
211
+ };
212
+ })(),
213
+ (async () => {
214
+ if (!properties.includes('nonce')) return undefined;
215
+ if (typeof parameters.nonce === 'bigint') return parameters.nonce;
216
+ return account.getNonce();
217
+ })(),
218
+ (async () => {
219
+ if (!properties.includes('authorization')) return undefined;
220
+ if (typeof parameters.authorization === 'object') return parameters.authorization;
221
+ if (account.authorization && !(await account.isDeployed())) {
222
+ const authorization = await prepareAuthorization(account.client, account.authorization);
223
+ return {
224
+ ...authorization,
225
+ r: '0xfffffffffffffffffffffffffffffff000000000000000000000000000000000',
226
+ s: '0x7aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
227
+ yParity: 1
228
+ } satisfies SignedAuthorization;
229
+ }
230
+ return undefined;
231
+ })()
232
+ ]);
233
+
234
+ ////////////////////////////////////////////////////////////////////////////////
235
+ // Fill User Operation with the prepared properties from above.
236
+ ////////////////////////////////////////////////////////////////////////////////
237
+
238
+ if (typeof callData !== 'undefined') request.callData = callData;
239
+ // biome-ignore lint/suspicious/noExplicitAny: copied from viem
240
+ if (typeof factory !== 'undefined') request = { ...request, ...(factory as any) };
241
+ // biome-ignore lint/suspicious/noExplicitAny: copied from viem
242
+ if (typeof fees !== 'undefined') request = { ...request, ...(fees as any) };
243
+ if (typeof nonce !== 'undefined') request.nonce = nonce;
244
+ if (typeof authorization !== 'undefined') request.authorization = authorization;
245
+
246
+ ////////////////////////////////////////////////////////////////////////////////
247
+ // Fill User Operation with the `signature` property.
248
+ ////////////////////////////////////////////////////////////////////////////////
249
+
250
+ if (properties.includes('signature')) {
251
+ if (typeof parameters.signature !== 'undefined') request.signature = parameters.signature;
252
+ else request.signature = await account.getStubSignature(request as UserOperation);
253
+ }
254
+
255
+ ////////////////////////////////////////////////////////////////////////////////
256
+ // `initCode` is required to be filled with EntryPoint 0.6.
257
+ ////////////////////////////////////////////////////////////////////////////////
258
+
259
+ // If no `initCode` is provided, we use an empty bytes string.
260
+ if (account.entryPoint.version === '0.6' && !request.initCode) request.initCode = '0x';
261
+
262
+ ////////////////////////////////////////////////////////////////////////////////
263
+ // Fill User Operation with paymaster-related properties for **gas estimation**.
264
+ ////////////////////////////////////////////////////////////////////////////////
265
+
266
+ let chainId: number | undefined;
267
+ async function getChainId(): Promise<number> {
268
+ if (chainId) return chainId;
269
+ if (client.chain) return client.chain.id;
270
+ const chainId_ = await getAction(client, getChainId_, 'getChainId')({});
271
+ chainId = chainId_;
272
+ return chainId;
273
+ }
274
+
275
+ // If the User Operation is intended to be sponsored, we will need to fill the paymaster-related
276
+ // User Operation properties required to estimate the User Operation gas.
277
+ let isPaymasterPopulated = false;
278
+ if (
279
+ properties.includes('paymaster') &&
280
+ getPaymasterStubData &&
281
+ !paymasterAddress &&
282
+ !parameters.paymasterAndData
283
+ ) {
284
+ const {
285
+ isFinal = false,
286
+ sponsor: _,
287
+ ...paymasterArgs
288
+ } = await getPaymasterStubData({
289
+ chainId: await getChainId(),
290
+ context: paymasterContext,
291
+ entryPointAddress: account.entryPoint.address,
292
+ ...(request as UserOperation)
293
+ });
294
+ isPaymasterPopulated = isFinal;
295
+ request = {
296
+ ...request,
297
+ ...paymasterArgs
298
+ } as PrepareUserOperationRequest;
299
+ }
300
+
301
+ ////////////////////////////////////////////////////////////////////////////////
302
+ // `paymasterAndData` is required to be filled with EntryPoint 0.6.
303
+ ////////////////////////////////////////////////////////////////////////////////
304
+
305
+ // If no `paymasterAndData` is provided, we use an empty bytes string.
306
+ if (account.entryPoint.version === '0.6' && !request.paymasterAndData)
307
+ request.paymasterAndData = '0x';
308
+
309
+ ////////////////////////////////////////////////////////////////////////////////
310
+ // Fill User Operation with gas-related properties.
311
+ ////////////////////////////////////////////////////////////////////////////////
312
+
313
+ if (quote && callsWithoutPayment && payment?.type === PaymentType.Token) {
314
+ const quote = await getUserOperationQuote(
315
+ bundlerClient,
316
+ {
317
+ account,
318
+ stateOverride,
319
+ ...request
320
+ },
321
+ capabilities,
322
+ payment
323
+ );
324
+
325
+ const calls = appendPayment(
326
+ callsWithoutPayment,
327
+ payment.address,
328
+ capabilities.feeCollector,
329
+ quote.fee
330
+ );
331
+
332
+ const callData = await account.encodeCalls(calls);
333
+
334
+ request = {
335
+ ...request,
336
+ callData,
337
+ callGasLimit: request.callGasLimit ?? quote.callGasLimit,
338
+ preVerificationGas: request.preVerificationGas ?? quote.preVerificationGas,
339
+ verificationGasLimit: request.verificationGasLimit ?? quote.verificationGasLimit
340
+ } as PrepareUserOperationRequest;
341
+ } else if (properties.includes('gas')) {
342
+ // If the Account has opinionated gas estimation logic, run the `estimateGas` hook and
343
+ // fill the request with the prepared gas properties.
344
+ if (account.userOperation?.estimateGas) {
345
+ const gas = await account.userOperation.estimateGas(request as UserOperation);
346
+ request = {
347
+ ...request,
348
+ ...gas
349
+ } as PrepareUserOperationRequest;
350
+ }
351
+
352
+ // If not all the gas properties are already populated, we will need to estimate the gas
353
+ // to fill the gas properties.
354
+ if (
355
+ typeof request.callGasLimit === 'undefined' ||
356
+ typeof request.preVerificationGas === 'undefined' ||
357
+ typeof request.verificationGasLimit === 'undefined' ||
358
+ (request.paymaster && typeof request.paymasterPostOpGasLimit === 'undefined') ||
359
+ (request.paymaster && typeof request.paymasterVerificationGasLimit === 'undefined')
360
+ ) {
361
+ const gas = await estimateUserOperationGas(
362
+ bundlerClient,
363
+ {
364
+ account,
365
+ // Some Bundlers fail if nullish gas values are provided for gas estimation :') –
366
+ // so we will need to set a default zeroish value.
367
+ callGasLimit: 0n,
368
+ preVerificationGas: 0n,
369
+ stateOverride,
370
+ verificationGasLimit: 0n,
371
+ ...(request.paymaster
372
+ ? {
373
+ paymasterPostOpGasLimit: 0n,
374
+ paymasterVerificationGasLimit: 0n
375
+ }
376
+ : {}),
377
+ ...request
378
+ } as EstimateUserOperationGasParameters,
379
+ capabilities,
380
+ payment
381
+ );
382
+ request = {
383
+ ...request,
384
+ callGasLimit: request.callGasLimit ?? gas.callGasLimit,
385
+ paymasterPostOpGasLimit: request.paymasterPostOpGasLimit ?? gas.paymasterPostOpGasLimit,
386
+ paymasterVerificationGasLimit:
387
+ request.paymasterVerificationGasLimit ?? gas.paymasterVerificationGasLimit,
388
+ preVerificationGas: request.preVerificationGas ?? gas.preVerificationGas,
389
+ verificationGasLimit: request.verificationGasLimit ?? gas.verificationGasLimit
390
+ } as PrepareUserOperationRequest;
391
+ }
392
+ }
393
+
394
+ ////////////////////////////////////////////////////////////////////////////////
395
+ // Fill User Operation with paymaster-related properties for **sending** the User Operation.
396
+ ////////////////////////////////////////////////////////////////////////////////
397
+
398
+ // If the User Operation is intended to be sponsored, we will need to fill the paymaster-related
399
+ // User Operation properties required to send the User Operation.
400
+ if (
401
+ properties.includes('paymaster') &&
402
+ getPaymasterData &&
403
+ !paymasterAddress &&
404
+ !parameters.paymasterAndData &&
405
+ !isPaymasterPopulated
406
+ ) {
407
+ // Retrieve paymaster-related User Operation properties to be used for **sending** the User Operation.
408
+ const paymaster = await getPaymasterData({
409
+ chainId: await getChainId(),
410
+ context: paymasterContext,
411
+ entryPointAddress: account.entryPoint.address,
412
+ ...(request as UserOperation)
413
+ });
414
+ request = {
415
+ ...request,
416
+ ...paymaster
417
+ } as PrepareUserOperationRequest;
418
+ }
419
+
420
+ ////////////////////////////////////////////////////////////////////////////////
421
+ // Remove redundant properties that do not conform to the User Operation schema.
422
+ ////////////////////////////////////////////////////////////////////////////////
423
+
424
+ delete request.calls;
425
+ delete request.parameters;
426
+ delete request.paymasterContext;
427
+ if (typeof request.paymaster !== 'string') delete request.paymaster;
428
+
429
+ ////////////////////////////////////////////////////////////////////////////////
430
+
431
+ return request as unknown as PrepareUserOperationReturnType<
432
+ account,
433
+ accountOverride,
434
+ calls,
435
+ request
436
+ >;
437
+ };
@@ -0,0 +1,64 @@
1
+ import type { BaseError, Chain, Client, Transport } from 'viem';
2
+ import {
3
+ formatUserOperationRequest,
4
+ getUserOperationError,
5
+ type PrepareUserOperationParameters,
6
+ type SendUserOperationParameters,
7
+ type SendUserOperationReturnType,
8
+ type SmartAccount,
9
+ type UserOperation
10
+ } from 'viem/account-abstraction';
11
+ import { parseAccount } from 'viem/accounts';
12
+ import type { CapabilitiesByChain } from '../../relayer/evm/actions/index.js';
13
+ import { AccountNotFoundError, type Payment } from '../../types/index.js';
14
+ import { prepareUserOperation } from './prepareUserOperation.js';
15
+
16
+ export const sendUserOperation = async <account extends SmartAccount | undefined>(
17
+ client: Client<Transport, Chain | undefined, account>,
18
+ parameters: SendUserOperationParameters,
19
+ capabilities: CapabilitiesByChain,
20
+ payment?: Payment
21
+ ): Promise<SendUserOperationReturnType> => {
22
+ const { account: account_ = client.account, entryPointAddress } = parameters;
23
+
24
+ if (!account_ && !parameters.sender) throw new AccountNotFoundError();
25
+ const account = account_ ? parseAccount(account_) : undefined;
26
+
27
+ const request = account
28
+ ? await prepareUserOperation(
29
+ client,
30
+ parameters as unknown as PrepareUserOperationParameters,
31
+ capabilities,
32
+ payment,
33
+ true
34
+ )
35
+ : parameters;
36
+
37
+ // biome-ignore lint/style/noNonNullAssertion: copied from viem
38
+ const signature = (parameters.signature ||
39
+ (await account?.signUserOperation?.(request as UserOperation)))!;
40
+
41
+ const rpcParameters = formatUserOperationRequest({
42
+ ...request,
43
+ signature
44
+ } as UserOperation);
45
+
46
+ try {
47
+ return await client.request(
48
+ {
49
+ method: 'eth_sendUserOperation',
50
+ // biome-ignore lint/style/noNonNullAssertion: copied from viem
51
+ params: [rpcParameters, (entryPointAddress ?? account?.entryPoint?.address)!]
52
+ },
53
+ { retryCount: 0 }
54
+ );
55
+ } catch (error) {
56
+ // biome-ignore lint/suspicious/noExplicitAny: copied from viem
57
+ const calls = (parameters as any).calls;
58
+ throw getUserOperationError(error as BaseError, {
59
+ ...(request as UserOperation),
60
+ ...(calls ? { calls } : {}),
61
+ signature
62
+ });
63
+ }
64
+ };
@@ -0,0 +1,71 @@
1
+ import type { BaseError, Chain, Client, Transport } from 'viem';
2
+ import {
3
+ formatUserOperationReceipt,
4
+ formatUserOperationRequest,
5
+ getUserOperationError,
6
+ type PrepareUserOperationParameters,
7
+ type SendUserOperationParameters,
8
+ type SmartAccount,
9
+ type UserOperation,
10
+ type UserOperationReceipt
11
+ } from 'viem/account-abstraction';
12
+ import { parseAccount } from 'viem/accounts';
13
+ import type { CapabilitiesByChain } from '../../relayer/evm/actions/index.js';
14
+ import { AccountNotFoundError, type Payment } from '../../types/index.js';
15
+ import { prepareUserOperation } from './prepareUserOperation.js';
16
+
17
+ export type SendUserOperationSyncParameters = SendUserOperationParameters & {
18
+ timeout: number;
19
+ };
20
+
21
+ export const sendUserOperationSync = async <account extends SmartAccount | undefined>(
22
+ client: Client<Transport, Chain | undefined, account>,
23
+ parameters: SendUserOperationSyncParameters,
24
+ capabilities: CapabilitiesByChain,
25
+ payment?: Payment
26
+ ): Promise<UserOperationReceipt> => {
27
+ const { account: account_ = client.account, entryPointAddress, timeout } = parameters;
28
+
29
+ if (!account_ && !parameters.sender) throw new AccountNotFoundError();
30
+ const account = account_ ? parseAccount(account_) : undefined;
31
+
32
+ const request = account
33
+ ? await prepareUserOperation(
34
+ client,
35
+ parameters as unknown as PrepareUserOperationParameters,
36
+ capabilities,
37
+ payment,
38
+ true
39
+ )
40
+ : parameters;
41
+
42
+ // biome-ignore lint/style/noNonNullAssertion: copied from viem
43
+ const signature = (parameters.signature ||
44
+ (await account?.signUserOperation?.(request as UserOperation)))!;
45
+
46
+ const rpcParameters = formatUserOperationRequest({
47
+ ...request,
48
+ signature
49
+ } as UserOperation);
50
+
51
+ try {
52
+ const receipt = await client.request(
53
+ {
54
+ method: 'eth_sendUserOperationSync',
55
+ // biome-ignore lint/style/noNonNullAssertion: copied from viem
56
+ params: [rpcParameters, (entryPointAddress ?? account?.entryPoint?.address)!, { timeout }]
57
+ } as never,
58
+ { retryCount: 0 }
59
+ );
60
+
61
+ return formatUserOperationReceipt(receipt);
62
+ } catch (error) {
63
+ // biome-ignore lint/suspicious/noExplicitAny: copied from viem
64
+ const calls = (parameters as any).calls;
65
+ throw getUserOperationError(error as BaseError, {
66
+ ...(request as UserOperation),
67
+ ...(calls ? { calls } : {}),
68
+ signature
69
+ });
70
+ }
71
+ };
@@ -0,0 +1,98 @@
1
+ import { type Chain, type Client, http, type Transport } from 'viem';
2
+ import {
3
+ type BundlerActions,
4
+ type BundlerClient,
5
+ type BundlerClientConfig,
6
+ createBundlerClient,
7
+ type UserOperationReceipt
8
+ } from 'viem/account-abstraction';
9
+ import { GELATO_PROD_API, GELATO_STAGING_API } from '../relayer/constants/index.js';
10
+ import { getCapabilities } from '../relayer/evm/actions/index.js';
11
+ import { type Payment, PaymentType } from '../types/index.js';
12
+ import {
13
+ estimateUserOperationGas,
14
+ type GetUserOperationGasPriceReturnType,
15
+ type GetUserOperationQuoteParameters,
16
+ type GetUserOperationQuoteReturnType,
17
+ getUserOperationGasPrice,
18
+ getUserOperationQuote,
19
+ prepareUserOperation,
20
+ type SendUserOperationSyncParameters,
21
+ sendUserOperation,
22
+ sendUserOperationSync
23
+ } from './actions/index.js';
24
+
25
+ export * from './actions/index.js';
26
+
27
+ export type GelatoBundlerActions = Partial<BundlerActions> & {
28
+ sendUserOperationSync: (
29
+ parameters: SendUserOperationSyncParameters
30
+ ) => Promise<UserOperationReceipt>;
31
+ getUserOperationGasPrice: () => Promise<GetUserOperationGasPriceReturnType>;
32
+ getUserOperationQuote: (
33
+ parameters: GetUserOperationQuoteParameters
34
+ ) => Promise<GetUserOperationQuoteReturnType>;
35
+ };
36
+
37
+ export type GelatoBundlerClient = BundlerClient & GelatoBundlerActions;
38
+
39
+ export type GelatoBundlerClientConfig = Omit<BundlerClientConfig, 'transport' | 'userOperation'> & {
40
+ client: Client<Transport, Chain>;
41
+ payment?: Payment;
42
+ apiKey: string;
43
+ };
44
+
45
+ export const createGelatoBundlerClient = async (
46
+ parameters: GelatoBundlerClientConfig
47
+ ): Promise<GelatoBundlerClient> => {
48
+ const { client: client_, payment, apiKey } = parameters;
49
+
50
+ // TODO: can just use prod endpoint in the future
51
+ const base = client_.chain.testnet ? GELATO_STAGING_API : GELATO_PROD_API;
52
+
53
+ let endpoint = `${base}/rpc/${client_.chain.id}`;
54
+
55
+ if (payment) {
56
+ endpoint += `?payment=${payment.type}`;
57
+
58
+ if (payment.type === PaymentType.Token) {
59
+ endpoint += `&address=${payment.address}`;
60
+ }
61
+ }
62
+
63
+ const transport = http(endpoint, {
64
+ fetchOptions: {
65
+ headers: {
66
+ 'X-API-Key': apiKey
67
+ }
68
+ }
69
+ });
70
+
71
+ const client = createBundlerClient({
72
+ ...parameters,
73
+ transport
74
+ });
75
+
76
+ const capabilities = (await getCapabilities(transport({})))[client_.chain.id];
77
+
78
+ if (!capabilities) {
79
+ throw new Error(`Chain not supported: ${client_.chain.id}`);
80
+ }
81
+
82
+ return client.extend(
83
+ (client) =>
84
+ ({
85
+ estimateUserOperationGas: (parameters) =>
86
+ estimateUserOperationGas(client, parameters, capabilities, payment),
87
+ getUserOperationGasPrice: () => getUserOperationGasPrice(client, payment),
88
+ getUserOperationQuote: (parameters) =>
89
+ getUserOperationQuote(client, parameters, capabilities, payment),
90
+ prepareUserOperation: (parameters) =>
91
+ prepareUserOperation(client, parameters, capabilities, payment),
92
+ sendUserOperation: (parameters) =>
93
+ sendUserOperation(client, parameters, capabilities, payment),
94
+ sendUserOperationSync: (parameters) =>
95
+ sendUserOperationSync(client, parameters, capabilities, payment)
96
+ }) as GelatoBundlerActions
97
+ ) as unknown as GelatoBundlerClient;
98
+ };