@t402/evm 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +183 -0
  2. package/dist/cjs/exact/client/index.d.ts +53 -0
  3. package/dist/cjs/exact/client/index.js +270 -0
  4. package/dist/cjs/exact/client/index.js.map +1 -0
  5. package/dist/cjs/exact/facilitator/index.d.ts +118 -0
  6. package/dist/cjs/exact/facilitator/index.js +735 -0
  7. package/dist/cjs/exact/facilitator/index.js.map +1 -0
  8. package/dist/cjs/exact/server/index.d.ts +36 -0
  9. package/dist/cjs/exact/server/index.js +438 -0
  10. package/dist/cjs/exact/server/index.js.map +1 -0
  11. package/dist/cjs/exact/v1/client/index.d.ts +37 -0
  12. package/dist/cjs/exact/v1/client/index.js +147 -0
  13. package/dist/cjs/exact/v1/client/index.js.map +1 -0
  14. package/dist/cjs/exact/v1/facilitator/index.d.ts +62 -0
  15. package/dist/cjs/exact/v1/facilitator/index.js +401 -0
  16. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -0
  17. package/dist/cjs/index.d.ts +1537 -0
  18. package/dist/cjs/index.js +2368 -0
  19. package/dist/cjs/index.js.map +1 -0
  20. package/dist/cjs/scheme-C6uD7PdY.d.ts +130 -0
  21. package/dist/cjs/scheme-OojTBKAz.d.ts +35 -0
  22. package/dist/cjs/scheme-yqGaK9rK.d.ts +130 -0
  23. package/dist/cjs/signer-BkcAzwYi.d.ts +79 -0
  24. package/dist/cjs/v1/index.d.ts +7 -0
  25. package/dist/cjs/v1/index.js +171 -0
  26. package/dist/cjs/v1/index.js.map +1 -0
  27. package/dist/esm/chunk-ACDQ5QNT.mjs +305 -0
  28. package/dist/esm/chunk-ACDQ5QNT.mjs.map +1 -0
  29. package/dist/esm/chunk-JBWWBRYY.mjs +92 -0
  30. package/dist/esm/chunk-JBWWBRYY.mjs.map +1 -0
  31. package/dist/esm/chunk-LGSG73NJ.mjs +88 -0
  32. package/dist/esm/chunk-LGSG73NJ.mjs.map +1 -0
  33. package/dist/esm/chunk-OEXW2OK2.mjs +251 -0
  34. package/dist/esm/chunk-OEXW2OK2.mjs.map +1 -0
  35. package/dist/esm/chunk-QLXM7BIB.mjs +23 -0
  36. package/dist/esm/chunk-QLXM7BIB.mjs.map +1 -0
  37. package/dist/esm/chunk-XYKAO6KJ.mjs +141 -0
  38. package/dist/esm/chunk-XYKAO6KJ.mjs.map +1 -0
  39. package/dist/esm/exact/client/index.d.mts +53 -0
  40. package/dist/esm/exact/client/index.mjs +36 -0
  41. package/dist/esm/exact/client/index.mjs.map +1 -0
  42. package/dist/esm/exact/facilitator/index.d.mts +118 -0
  43. package/dist/esm/exact/facilitator/index.mjs +324 -0
  44. package/dist/esm/exact/facilitator/index.mjs.map +1 -0
  45. package/dist/esm/exact/server/index.d.mts +36 -0
  46. package/dist/esm/exact/server/index.mjs +218 -0
  47. package/dist/esm/exact/server/index.mjs.map +1 -0
  48. package/dist/esm/exact/v1/client/index.d.mts +37 -0
  49. package/dist/esm/exact/v1/client/index.mjs +8 -0
  50. package/dist/esm/exact/v1/client/index.mjs.map +1 -0
  51. package/dist/esm/exact/v1/facilitator/index.d.mts +62 -0
  52. package/dist/esm/exact/v1/facilitator/index.mjs +8 -0
  53. package/dist/esm/exact/v1/facilitator/index.mjs.map +1 -0
  54. package/dist/esm/index.d.mts +1537 -0
  55. package/dist/esm/index.mjs +1875 -0
  56. package/dist/esm/index.mjs.map +1 -0
  57. package/dist/esm/scheme-D4mOqq9l.d.mts +35 -0
  58. package/dist/esm/scheme-yqGaK9rK.d.mts +130 -0
  59. package/dist/esm/signer-BkcAzwYi.d.mts +79 -0
  60. package/dist/esm/v1/index.d.mts +7 -0
  61. package/dist/esm/v1/index.mjs +13 -0
  62. package/dist/esm/v1/index.mjs.map +1 -0
  63. package/package.json +127 -0
@@ -0,0 +1,1875 @@
1
+ import {
2
+ ExactEvmScheme
3
+ } from "./chunk-LGSG73NJ.mjs";
4
+ import {
5
+ TOKEN_PRIORITY,
6
+ TOKEN_REGISTRY,
7
+ USDC_ADDRESSES,
8
+ USDT0_ADDRESSES,
9
+ USDT_LEGACY_ADDRESSES,
10
+ getDefaultToken,
11
+ getEIP712Domain,
12
+ getNetworkTokens,
13
+ getNetworksForToken,
14
+ getTokenByAddress,
15
+ getTokenConfig,
16
+ getUsdt0Networks,
17
+ supportsEIP3009
18
+ } from "./chunk-OEXW2OK2.mjs";
19
+ import {
20
+ authorizationTypes,
21
+ createNonce,
22
+ eip3009ABI,
23
+ erc20LegacyABI,
24
+ legacyAuthorizationTypes
25
+ } from "./chunk-XYKAO6KJ.mjs";
26
+
27
+ // src/exact-legacy/client/scheme.ts
28
+ import { getAddress } from "viem";
29
+ var ExactLegacyEvmScheme = class {
30
+ /**
31
+ * Creates a new ExactLegacyEvmScheme instance.
32
+ *
33
+ * @param signer - The EVM signer for client operations
34
+ */
35
+ constructor(signer) {
36
+ this.signer = signer;
37
+ this.scheme = "exact-legacy";
38
+ }
39
+ /**
40
+ * Creates a payment payload for the exact-legacy scheme.
41
+ *
42
+ * @param t402Version - The t402 protocol version
43
+ * @param paymentRequirements - The payment requirements
44
+ * @returns Promise resolving to a payment payload
45
+ */
46
+ async createPaymentPayload(t402Version, paymentRequirements) {
47
+ if (!paymentRequirements.extra?.spender) {
48
+ throw new Error(
49
+ "exact-legacy scheme requires 'spender' (facilitator address) in payment requirements extra field"
50
+ );
51
+ }
52
+ const spender = getAddress(paymentRequirements.extra.spender);
53
+ const nonce = createNonce();
54
+ const now = Math.floor(Date.now() / 1e3);
55
+ const authorization = {
56
+ from: this.signer.address,
57
+ to: getAddress(paymentRequirements.payTo),
58
+ value: paymentRequirements.amount,
59
+ validAfter: (now - 600).toString(),
60
+ // 10 minutes before
61
+ validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),
62
+ nonce,
63
+ spender
64
+ };
65
+ const signature = await this.signAuthorization(authorization, paymentRequirements);
66
+ const payload = {
67
+ authorization,
68
+ signature
69
+ };
70
+ return {
71
+ t402Version,
72
+ payload
73
+ };
74
+ }
75
+ /**
76
+ * Sign the legacy transfer authorization using EIP-712
77
+ *
78
+ * @param authorization - The authorization to sign
79
+ * @param requirements - The payment requirements
80
+ * @returns Promise resolving to the signature
81
+ */
82
+ async signAuthorization(authorization, requirements) {
83
+ const chainId = parseInt(requirements.network.split(":")[1]);
84
+ const name = requirements.extra?.name || "T402LegacyTransfer";
85
+ const version = requirements.extra?.version || "1";
86
+ const domain = {
87
+ name,
88
+ version,
89
+ chainId,
90
+ verifyingContract: getAddress(requirements.asset)
91
+ };
92
+ const message = {
93
+ from: getAddress(authorization.from),
94
+ to: getAddress(authorization.to),
95
+ value: BigInt(authorization.value),
96
+ validAfter: BigInt(authorization.validAfter),
97
+ validBefore: BigInt(authorization.validBefore),
98
+ nonce: authorization.nonce,
99
+ spender: getAddress(authorization.spender)
100
+ };
101
+ return await this.signer.signTypedData({
102
+ domain,
103
+ types: legacyAuthorizationTypes,
104
+ primaryType: "LegacyTransferAuthorization",
105
+ message
106
+ });
107
+ }
108
+ };
109
+
110
+ // src/exact-legacy/server/scheme.ts
111
+ var ExactLegacyEvmScheme2 = class {
112
+ constructor(config = {}) {
113
+ this.scheme = "exact-legacy";
114
+ this.moneyParsers = [];
115
+ this.config = config;
116
+ }
117
+ /**
118
+ * Register a custom money parser in the parser chain.
119
+ */
120
+ registerMoneyParser(parser) {
121
+ this.moneyParsers.push(parser);
122
+ return this;
123
+ }
124
+ /**
125
+ * Parses a price into an asset amount for legacy tokens.
126
+ */
127
+ async parsePrice(price, network) {
128
+ if (typeof price === "object" && price !== null && "amount" in price) {
129
+ if (!price.asset) {
130
+ throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);
131
+ }
132
+ return {
133
+ amount: price.amount,
134
+ asset: price.asset,
135
+ extra: {
136
+ ...price.extra,
137
+ tokenType: "legacy"
138
+ }
139
+ };
140
+ }
141
+ const amount = this.parseMoneyToDecimal(price);
142
+ for (const parser of this.moneyParsers) {
143
+ const result = await parser(amount, network);
144
+ if (result !== null) {
145
+ return result;
146
+ }
147
+ }
148
+ return this.defaultMoneyConversion(amount, network);
149
+ }
150
+ /**
151
+ * Build payment requirements for this scheme/network combination.
152
+ * Adds the spender (facilitator) address to the extra field.
153
+ */
154
+ enhancePaymentRequirements(paymentRequirements, supportedKind, extensionKeys) {
155
+ void extensionKeys;
156
+ const spender = supportedKind.extra?.spender;
157
+ return Promise.resolve({
158
+ ...paymentRequirements,
159
+ extra: {
160
+ ...paymentRequirements.extra,
161
+ tokenType: "legacy",
162
+ ...spender && { spender }
163
+ }
164
+ });
165
+ }
166
+ /**
167
+ * Parse Money (string | number) to a decimal number.
168
+ */
169
+ parseMoneyToDecimal(money) {
170
+ if (typeof money === "number") {
171
+ return money;
172
+ }
173
+ const cleanMoney = money.replace(/^\$/, "").trim();
174
+ const amount = parseFloat(cleanMoney);
175
+ if (isNaN(amount)) {
176
+ throw new Error(`Invalid money format: ${money}`);
177
+ }
178
+ return amount;
179
+ }
180
+ /**
181
+ * Default money conversion implementation for legacy tokens.
182
+ */
183
+ defaultMoneyConversion(amount, network) {
184
+ const token = this.getDefaultAsset(network);
185
+ const tokenAmount = this.convertToTokenAmount(amount.toString(), token.decimals);
186
+ return {
187
+ amount: tokenAmount,
188
+ asset: token.address,
189
+ extra: {
190
+ name: token.name,
191
+ version: token.version,
192
+ symbol: token.symbol,
193
+ tokenType: "legacy"
194
+ }
195
+ };
196
+ }
197
+ /**
198
+ * Convert decimal amount to token units
199
+ */
200
+ convertToTokenAmount(decimalAmount, decimals) {
201
+ const amount = parseFloat(decimalAmount);
202
+ if (isNaN(amount)) {
203
+ throw new Error(`Invalid amount: ${decimalAmount}`);
204
+ }
205
+ const tokenAmount = Math.floor(amount * Math.pow(10, decimals));
206
+ return tokenAmount.toString();
207
+ }
208
+ /**
209
+ * Get the default legacy token for a network.
210
+ */
211
+ getDefaultAsset(network) {
212
+ if (this.config.preferredToken) {
213
+ const preferred = getTokenConfig(network, this.config.preferredToken);
214
+ if (preferred && preferred.tokenType === "legacy") {
215
+ return preferred;
216
+ }
217
+ }
218
+ const usdt = getTokenConfig(network, "USDT");
219
+ if (usdt && usdt.tokenType === "legacy") {
220
+ return usdt;
221
+ }
222
+ const tokens = TOKEN_REGISTRY[network];
223
+ if (tokens) {
224
+ const legacyToken = Object.values(tokens).find((t) => t.tokenType === "legacy");
225
+ if (legacyToken) return legacyToken;
226
+ }
227
+ throw new Error(`No legacy tokens configured for network ${network}`);
228
+ }
229
+ /**
230
+ * Get all supported networks that have legacy tokens
231
+ */
232
+ static getSupportedNetworks() {
233
+ return Object.keys(USDT_LEGACY_ADDRESSES);
234
+ }
235
+ /**
236
+ * Check if a network has legacy token support
237
+ */
238
+ static isNetworkSupported(network) {
239
+ return network in USDT_LEGACY_ADDRESSES;
240
+ }
241
+ };
242
+
243
+ // src/exact-legacy/facilitator/scheme.ts
244
+ import { getAddress as getAddress2, isAddressEqual } from "viem";
245
+ var ExactLegacyEvmScheme3 = class {
246
+ /**
247
+ * Creates a new ExactLegacyEvmScheme instance.
248
+ *
249
+ * @param signer - The EVM signer for facilitator operations
250
+ * @param config - Optional configuration
251
+ */
252
+ constructor(signer, config) {
253
+ this.signer = signer;
254
+ this.scheme = "exact-legacy";
255
+ this.caipFamily = "eip155:*";
256
+ this.config = {
257
+ minAllowanceRatio: config?.minAllowanceRatio ?? 1
258
+ };
259
+ }
260
+ /**
261
+ * Get mechanism-specific extra data for the supported kinds endpoint.
262
+ * For exact-legacy, returns the spender (facilitator) addresses.
263
+ *
264
+ * @param network - The network identifier
265
+ * @returns Extra data including spender addresses
266
+ */
267
+ getExtra(network) {
268
+ void network;
269
+ const addresses = this.signer.getAddresses();
270
+ if (addresses.length > 0) {
271
+ return {
272
+ spender: addresses[0],
273
+ tokenType: "legacy"
274
+ };
275
+ }
276
+ return { tokenType: "legacy" };
277
+ }
278
+ /**
279
+ * Get signer addresses used by this facilitator.
280
+ */
281
+ getSigners(network) {
282
+ void network;
283
+ return [...this.signer.getAddresses()];
284
+ }
285
+ /**
286
+ * Verifies a payment payload.
287
+ */
288
+ async verify(payload, requirements) {
289
+ const legacyPayload = payload.payload;
290
+ if (payload.accepted.scheme !== "exact-legacy" || requirements.scheme !== "exact-legacy") {
291
+ return {
292
+ isValid: false,
293
+ invalidReason: "unsupported_scheme",
294
+ payer: legacyPayload.authorization.from
295
+ };
296
+ }
297
+ if (payload.accepted.network !== requirements.network) {
298
+ return {
299
+ isValid: false,
300
+ invalidReason: "network_mismatch",
301
+ payer: legacyPayload.authorization.from
302
+ };
303
+ }
304
+ const erc20Address = getAddress2(requirements.asset);
305
+ const spender = getAddress2(legacyPayload.authorization.spender);
306
+ const facilitatorAddresses = this.signer.getAddresses();
307
+ const isValidSpender = facilitatorAddresses.some((addr) => isAddressEqual(addr, spender));
308
+ if (!isValidSpender) {
309
+ return {
310
+ isValid: false,
311
+ invalidReason: "invalid_spender",
312
+ payer: legacyPayload.authorization.from
313
+ };
314
+ }
315
+ const name = requirements.extra?.name || "T402LegacyTransfer";
316
+ const version = requirements.extra?.version || "1";
317
+ const chainId = parseInt(requirements.network.split(":")[1]);
318
+ const domain = {
319
+ name,
320
+ version,
321
+ chainId,
322
+ verifyingContract: erc20Address
323
+ };
324
+ const message = {
325
+ from: legacyPayload.authorization.from,
326
+ to: legacyPayload.authorization.to,
327
+ value: BigInt(legacyPayload.authorization.value),
328
+ validAfter: BigInt(legacyPayload.authorization.validAfter),
329
+ validBefore: BigInt(legacyPayload.authorization.validBefore),
330
+ nonce: legacyPayload.authorization.nonce,
331
+ spender: legacyPayload.authorization.spender
332
+ };
333
+ try {
334
+ const isValid = await this.signer.verifyTypedData({
335
+ address: legacyPayload.authorization.from,
336
+ domain,
337
+ types: legacyAuthorizationTypes,
338
+ primaryType: "LegacyTransferAuthorization",
339
+ message,
340
+ signature: legacyPayload.signature
341
+ });
342
+ if (!isValid) {
343
+ return {
344
+ isValid: false,
345
+ invalidReason: "invalid_signature",
346
+ payer: legacyPayload.authorization.from
347
+ };
348
+ }
349
+ } catch {
350
+ return {
351
+ isValid: false,
352
+ invalidReason: "signature_verification_failed",
353
+ payer: legacyPayload.authorization.from
354
+ };
355
+ }
356
+ if (getAddress2(legacyPayload.authorization.to) !== getAddress2(requirements.payTo)) {
357
+ return {
358
+ isValid: false,
359
+ invalidReason: "recipient_mismatch",
360
+ payer: legacyPayload.authorization.from
361
+ };
362
+ }
363
+ const now = Math.floor(Date.now() / 1e3);
364
+ if (BigInt(legacyPayload.authorization.validBefore) < BigInt(now + 6)) {
365
+ return {
366
+ isValid: false,
367
+ invalidReason: "authorization_expired",
368
+ payer: legacyPayload.authorization.from
369
+ };
370
+ }
371
+ if (BigInt(legacyPayload.authorization.validAfter) > BigInt(now)) {
372
+ return {
373
+ isValid: false,
374
+ invalidReason: "authorization_not_yet_valid",
375
+ payer: legacyPayload.authorization.from
376
+ };
377
+ }
378
+ try {
379
+ const balance = await this.signer.readContract({
380
+ address: erc20Address,
381
+ abi: erc20LegacyABI,
382
+ functionName: "balanceOf",
383
+ args: [legacyPayload.authorization.from]
384
+ });
385
+ if (BigInt(balance) < BigInt(requirements.amount)) {
386
+ return {
387
+ isValid: false,
388
+ invalidReason: "insufficient_balance",
389
+ payer: legacyPayload.authorization.from
390
+ };
391
+ }
392
+ } catch {
393
+ }
394
+ try {
395
+ const allowance = await this.signer.readContract({
396
+ address: erc20Address,
397
+ abi: erc20LegacyABI,
398
+ functionName: "allowance",
399
+ args: [legacyPayload.authorization.from, spender]
400
+ });
401
+ const requiredAllowance = BigInt(
402
+ Math.floor(Number(requirements.amount) * this.config.minAllowanceRatio)
403
+ );
404
+ if (allowance < requiredAllowance) {
405
+ return {
406
+ isValid: false,
407
+ invalidReason: "insufficient_allowance",
408
+ payer: legacyPayload.authorization.from
409
+ };
410
+ }
411
+ } catch {
412
+ return {
413
+ isValid: false,
414
+ invalidReason: "allowance_check_failed",
415
+ payer: legacyPayload.authorization.from
416
+ };
417
+ }
418
+ if (BigInt(legacyPayload.authorization.value) < BigInt(requirements.amount)) {
419
+ return {
420
+ isValid: false,
421
+ invalidReason: "insufficient_amount",
422
+ payer: legacyPayload.authorization.from
423
+ };
424
+ }
425
+ return {
426
+ isValid: true,
427
+ invalidReason: void 0,
428
+ payer: legacyPayload.authorization.from
429
+ };
430
+ }
431
+ /**
432
+ * Settles a payment by executing transferFrom.
433
+ */
434
+ async settle(payload, requirements) {
435
+ const legacyPayload = payload.payload;
436
+ const valid = await this.verify(payload, requirements);
437
+ if (!valid.isValid) {
438
+ return {
439
+ success: false,
440
+ network: payload.accepted.network,
441
+ transaction: "",
442
+ errorReason: valid.invalidReason ?? "invalid_payment",
443
+ payer: legacyPayload.authorization.from
444
+ };
445
+ }
446
+ try {
447
+ const tx = await this.signer.writeContract({
448
+ address: getAddress2(requirements.asset),
449
+ abi: erc20LegacyABI,
450
+ functionName: "transferFrom",
451
+ args: [
452
+ getAddress2(legacyPayload.authorization.from),
453
+ getAddress2(legacyPayload.authorization.to),
454
+ BigInt(legacyPayload.authorization.value)
455
+ ]
456
+ });
457
+ const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
458
+ if (receipt.status !== "success") {
459
+ return {
460
+ success: false,
461
+ errorReason: "transaction_failed",
462
+ transaction: tx,
463
+ network: payload.accepted.network,
464
+ payer: legacyPayload.authorization.from
465
+ };
466
+ }
467
+ return {
468
+ success: true,
469
+ transaction: tx,
470
+ network: payload.accepted.network,
471
+ payer: legacyPayload.authorization.from
472
+ };
473
+ } catch (error) {
474
+ console.error("Failed to settle legacy transaction:", error);
475
+ return {
476
+ success: false,
477
+ errorReason: "settlement_failed",
478
+ transaction: "",
479
+ network: payload.accepted.network,
480
+ payer: legacyPayload.authorization.from
481
+ };
482
+ }
483
+ }
484
+ };
485
+
486
+ // src/signer.ts
487
+ function toClientEvmSigner(signer) {
488
+ return signer;
489
+ }
490
+ function toFacilitatorEvmSigner(client) {
491
+ return {
492
+ ...client,
493
+ getAddresses: () => [client.address]
494
+ };
495
+ }
496
+
497
+ // src/bridge/constants.ts
498
+ var LAYERZERO_ENDPOINT_IDS = {
499
+ // Mainnets
500
+ ethereum: 30101,
501
+ arbitrum: 30110,
502
+ base: 30184,
503
+ optimism: 30111,
504
+ polygon: 30109,
505
+ avalanche: 30106,
506
+ bsc: 30102,
507
+ // USDT0 specific chains
508
+ ink: 30291,
509
+ // Ink mainnet
510
+ berachain: 30362,
511
+ // Berachain mainnet
512
+ unichain: 30320,
513
+ // Unichain mainnet
514
+ // Testnets
515
+ sepolia: 40161,
516
+ arbitrumSepolia: 40231,
517
+ baseSepolia: 40245
518
+ };
519
+ var NETWORK_TO_CHAIN = {
520
+ "eip155:1": "ethereum",
521
+ "eip155:42161": "arbitrum",
522
+ "eip155:8453": "base",
523
+ "eip155:10": "optimism",
524
+ "eip155:137": "polygon",
525
+ "eip155:43114": "avalanche",
526
+ "eip155:56": "bsc",
527
+ "eip155:57073": "ink",
528
+ "eip155:80094": "berachain",
529
+ "eip155:130": "unichain",
530
+ // Testnets
531
+ "eip155:11155111": "sepolia",
532
+ "eip155:421614": "arbitrumSepolia",
533
+ "eip155:84532": "baseSepolia"
534
+ };
535
+ var CHAIN_TO_NETWORK = Object.fromEntries(
536
+ Object.entries(NETWORK_TO_CHAIN).map(([k, v]) => [v, k])
537
+ );
538
+ var USDT0_OFT_ADDRESSES = {
539
+ // Ethereum is the OFT Adapter (locks/unlocks tokens)
540
+ ethereum: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee",
541
+ // Other chains have native USDT0 OFT contracts
542
+ arbitrum: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
543
+ ink: "0x0200C29006150606B650577BBE7B6248F58470c1",
544
+ berachain: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
545
+ unichain: "0x588ce4F028D8e7B53B687865d6A67b3A54C75518"
546
+ };
547
+ var LAYERZERO_ENDPOINT_V2 = "0x1a44076050125825900e736c501f859c50fE728c";
548
+ var DEFAULT_EXTRA_OPTIONS = "0x00030100110100000000000000000000000000030d40";
549
+ var OFT_SEND_ABI = [
550
+ {
551
+ inputs: [
552
+ {
553
+ components: [
554
+ { name: "dstEid", type: "uint32" },
555
+ { name: "to", type: "bytes32" },
556
+ { name: "amountLD", type: "uint256" },
557
+ { name: "minAmountLD", type: "uint256" },
558
+ { name: "extraOptions", type: "bytes" },
559
+ { name: "composeMsg", type: "bytes" },
560
+ { name: "oftCmd", type: "bytes" }
561
+ ],
562
+ name: "_sendParam",
563
+ type: "tuple"
564
+ },
565
+ {
566
+ components: [
567
+ { name: "nativeFee", type: "uint256" },
568
+ { name: "lzTokenFee", type: "uint256" }
569
+ ],
570
+ name: "_fee",
571
+ type: "tuple"
572
+ },
573
+ { name: "_refundAddress", type: "address" }
574
+ ],
575
+ name: "send",
576
+ outputs: [
577
+ {
578
+ components: [
579
+ { name: "guid", type: "bytes32" },
580
+ { name: "nonce", type: "uint64" },
581
+ {
582
+ components: [
583
+ { name: "nativeFee", type: "uint256" },
584
+ { name: "lzTokenFee", type: "uint256" }
585
+ ],
586
+ name: "fee",
587
+ type: "tuple"
588
+ }
589
+ ],
590
+ name: "msgReceipt",
591
+ type: "tuple"
592
+ },
593
+ {
594
+ components: [
595
+ { name: "amountSentLD", type: "uint256" },
596
+ { name: "amountReceivedLD", type: "uint256" }
597
+ ],
598
+ name: "oftReceipt",
599
+ type: "tuple"
600
+ }
601
+ ],
602
+ stateMutability: "payable",
603
+ type: "function"
604
+ },
605
+ {
606
+ inputs: [
607
+ {
608
+ components: [
609
+ { name: "dstEid", type: "uint32" },
610
+ { name: "to", type: "bytes32" },
611
+ { name: "amountLD", type: "uint256" },
612
+ { name: "minAmountLD", type: "uint256" },
613
+ { name: "extraOptions", type: "bytes" },
614
+ { name: "composeMsg", type: "bytes" },
615
+ { name: "oftCmd", type: "bytes" }
616
+ ],
617
+ name: "_sendParam",
618
+ type: "tuple"
619
+ },
620
+ { name: "_payInLzToken", type: "bool" }
621
+ ],
622
+ name: "quoteSend",
623
+ outputs: [
624
+ {
625
+ components: [
626
+ { name: "nativeFee", type: "uint256" },
627
+ { name: "lzTokenFee", type: "uint256" }
628
+ ],
629
+ name: "msgFee",
630
+ type: "tuple"
631
+ }
632
+ ],
633
+ stateMutability: "view",
634
+ type: "function"
635
+ }
636
+ ];
637
+ var ERC20_APPROVE_ABI = [
638
+ {
639
+ inputs: [
640
+ { name: "spender", type: "address" },
641
+ { name: "amount", type: "uint256" }
642
+ ],
643
+ name: "approve",
644
+ outputs: [{ name: "", type: "bool" }],
645
+ stateMutability: "nonpayable",
646
+ type: "function"
647
+ },
648
+ {
649
+ inputs: [
650
+ { name: "owner", type: "address" },
651
+ { name: "spender", type: "address" }
652
+ ],
653
+ name: "allowance",
654
+ outputs: [{ name: "", type: "uint256" }],
655
+ stateMutability: "view",
656
+ type: "function"
657
+ }
658
+ ];
659
+ function getEndpointId(chain) {
660
+ return LAYERZERO_ENDPOINT_IDS[chain];
661
+ }
662
+ function getUsdt0OftAddress(chain) {
663
+ return USDT0_OFT_ADDRESSES[chain];
664
+ }
665
+ function supportsBridging(chain) {
666
+ return chain in USDT0_OFT_ADDRESSES && chain in LAYERZERO_ENDPOINT_IDS;
667
+ }
668
+ function getBridgeableChains() {
669
+ return Object.keys(USDT0_OFT_ADDRESSES).filter(
670
+ (chain) => chain in LAYERZERO_ENDPOINT_IDS
671
+ );
672
+ }
673
+ function addressToBytes32(address) {
674
+ const cleanAddress = address.slice(2).toLowerCase();
675
+ return `0x${cleanAddress.padStart(64, "0")}`;
676
+ }
677
+ function bytes32ToAddress(bytes32) {
678
+ return `0x${bytes32.slice(-40)}`;
679
+ }
680
+
681
+ // src/bridge/client.ts
682
+ var DEFAULT_SLIPPAGE = 0.5;
683
+ var ESTIMATED_BRIDGE_TIME = 300;
684
+ var Usdt0Bridge = class {
685
+ /**
686
+ * Create a new bridge client
687
+ *
688
+ * @param signer - Wallet signer with read/write capabilities
689
+ * @param chain - Source chain name (e.g., "arbitrum", "ethereum")
690
+ */
691
+ constructor(signer, chain) {
692
+ if (!supportsBridging(chain)) {
693
+ throw new Error(
694
+ `Chain "${chain}" does not support USDT0 bridging. Supported chains: ${getBridgeableChains().join(", ")}`
695
+ );
696
+ }
697
+ this.signer = signer;
698
+ this.chain = chain;
699
+ }
700
+ /**
701
+ * Get a quote for bridging USDT0
702
+ *
703
+ * @param params - Bridge parameters
704
+ * @returns Quote with fee and amount information
705
+ */
706
+ async quote(params) {
707
+ this.validateBridgeParams(params);
708
+ const sendParam = this.buildSendParam(params);
709
+ const oftAddress = getUsdt0OftAddress(params.fromChain);
710
+ const fee = await this.signer.readContract({
711
+ address: oftAddress,
712
+ abi: OFT_SEND_ABI,
713
+ functionName: "quoteSend",
714
+ args: [sendParam, false]
715
+ });
716
+ return {
717
+ nativeFee: fee.nativeFee,
718
+ amountToSend: params.amount,
719
+ minAmountToReceive: sendParam.minAmountLD,
720
+ estimatedTime: ESTIMATED_BRIDGE_TIME,
721
+ fromChain: params.fromChain,
722
+ toChain: params.toChain
723
+ };
724
+ }
725
+ /**
726
+ * Execute a bridge transaction
727
+ *
728
+ * @param params - Bridge execution parameters
729
+ * @returns Bridge result with transaction hash
730
+ */
731
+ async send(params) {
732
+ this.validateBridgeParams(params);
733
+ const oftAddress = getUsdt0OftAddress(params.fromChain);
734
+ const sendParam = this.buildSendParam(params);
735
+ const refundAddress = params.refundAddress ?? this.signer.address;
736
+ const fee = await this.signer.readContract({
737
+ address: oftAddress,
738
+ abi: OFT_SEND_ABI,
739
+ functionName: "quoteSend",
740
+ args: [sendParam, false]
741
+ });
742
+ await this.ensureAllowance(oftAddress, params.amount);
743
+ const txHash = await this.signer.writeContract({
744
+ address: oftAddress,
745
+ abi: OFT_SEND_ABI,
746
+ functionName: "send",
747
+ args: [sendParam, fee, refundAddress],
748
+ value: fee.nativeFee
749
+ });
750
+ const receipt = await this.signer.waitForTransactionReceipt({ hash: txHash });
751
+ if (receipt.status !== "success") {
752
+ throw new Error(`Bridge transaction failed: ${txHash}`);
753
+ }
754
+ return {
755
+ txHash,
756
+ messageGuid: "0x" + "0".repeat(64),
757
+ // Would be extracted from event logs
758
+ amountSent: params.amount,
759
+ amountToReceive: sendParam.minAmountLD,
760
+ fromChain: params.fromChain,
761
+ toChain: params.toChain,
762
+ estimatedTime: ESTIMATED_BRIDGE_TIME
763
+ };
764
+ }
765
+ /**
766
+ * Ensure sufficient token allowance for the OFT contract
767
+ */
768
+ async ensureAllowance(oftAddress, amount) {
769
+ const allowance = await this.signer.readContract({
770
+ address: oftAddress,
771
+ abi: ERC20_APPROVE_ABI,
772
+ functionName: "allowance",
773
+ args: [this.signer.address, oftAddress]
774
+ });
775
+ if (allowance < amount) {
776
+ const approveTx = await this.signer.writeContract({
777
+ address: oftAddress,
778
+ abi: ERC20_APPROVE_ABI,
779
+ functionName: "approve",
780
+ args: [oftAddress, amount]
781
+ });
782
+ await this.signer.waitForTransactionReceipt({ hash: approveTx });
783
+ }
784
+ }
785
+ /**
786
+ * Build SendParam struct for LayerZero
787
+ */
788
+ buildSendParam(params) {
789
+ const dstEid = getEndpointId(params.toChain);
790
+ if (!dstEid) {
791
+ throw new Error(`Unknown destination chain: ${params.toChain}`);
792
+ }
793
+ const slippage = "slippageTolerance" in params ? params.slippageTolerance ?? DEFAULT_SLIPPAGE : DEFAULT_SLIPPAGE;
794
+ const minAmount = params.amount - params.amount * BigInt(Math.floor(slippage * 100)) / 10000n;
795
+ return {
796
+ dstEid,
797
+ to: addressToBytes32(params.recipient),
798
+ amountLD: params.amount,
799
+ minAmountLD: minAmount,
800
+ extraOptions: DEFAULT_EXTRA_OPTIONS,
801
+ composeMsg: "0x",
802
+ oftCmd: "0x"
803
+ };
804
+ }
805
+ /**
806
+ * Validate bridge parameters
807
+ */
808
+ validateBridgeParams(params) {
809
+ if (params.fromChain !== this.chain) {
810
+ throw new Error(
811
+ `Source chain mismatch: bridge initialized for "${this.chain}" but got "${params.fromChain}"`
812
+ );
813
+ }
814
+ if (!supportsBridging(params.fromChain)) {
815
+ throw new Error(`Source chain "${params.fromChain}" does not support USDT0 bridging`);
816
+ }
817
+ if (!supportsBridging(params.toChain)) {
818
+ throw new Error(`Destination chain "${params.toChain}" does not support USDT0 bridging`);
819
+ }
820
+ if (params.fromChain === params.toChain) {
821
+ throw new Error("Source and destination chains must be different");
822
+ }
823
+ if (params.amount <= 0n) {
824
+ throw new Error("Amount must be greater than 0");
825
+ }
826
+ }
827
+ /**
828
+ * Get all supported destination chains from current chain
829
+ */
830
+ getSupportedDestinations() {
831
+ return getBridgeableChains().filter((chain) => chain !== this.chain);
832
+ }
833
+ /**
834
+ * Check if a destination chain is supported
835
+ */
836
+ supportsDestination(toChain) {
837
+ return toChain !== this.chain && supportsBridging(toChain);
838
+ }
839
+ };
840
+ function createUsdt0Bridge(signer, chain) {
841
+ return new Usdt0Bridge(signer, chain);
842
+ }
843
+
844
+ // src/erc4337/constants.ts
845
+ var ENTRYPOINT_V07_ADDRESS = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
846
+ var ENTRYPOINT_V06_ADDRESS = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
847
+ var DEFAULT_GAS_LIMITS = {
848
+ /** Gas for account validation */
849
+ verificationGasLimit: 150000n,
850
+ /** Gas for callData execution */
851
+ callGasLimit: 100000n,
852
+ /** Gas paid to bundler for overhead */
853
+ preVerificationGas: 50000n,
854
+ /** Gas for paymaster validation */
855
+ paymasterVerificationGasLimit: 50000n,
856
+ /** Gas for paymaster post-op */
857
+ paymasterPostOpGasLimit: 50000n
858
+ };
859
+ var ENTRYPOINT_V07_ABI = [
860
+ {
861
+ inputs: [
862
+ {
863
+ components: [
864
+ { name: "sender", type: "address" },
865
+ { name: "nonce", type: "uint256" },
866
+ { name: "initCode", type: "bytes" },
867
+ { name: "callData", type: "bytes" },
868
+ { name: "accountGasLimits", type: "bytes32" },
869
+ { name: "preVerificationGas", type: "uint256" },
870
+ { name: "gasFees", type: "bytes32" },
871
+ { name: "paymasterAndData", type: "bytes" },
872
+ { name: "signature", type: "bytes" }
873
+ ],
874
+ name: "ops",
875
+ type: "tuple[]"
876
+ },
877
+ { name: "beneficiary", type: "address" }
878
+ ],
879
+ name: "handleOps",
880
+ outputs: [],
881
+ stateMutability: "nonpayable",
882
+ type: "function"
883
+ },
884
+ {
885
+ inputs: [{ name: "sender", type: "address" }],
886
+ name: "getNonce",
887
+ outputs: [{ name: "nonce", type: "uint256" }],
888
+ stateMutability: "view",
889
+ type: "function"
890
+ },
891
+ {
892
+ inputs: [
893
+ { name: "sender", type: "address" },
894
+ { name: "key", type: "uint192" }
895
+ ],
896
+ name: "getNonce",
897
+ outputs: [{ name: "nonce", type: "uint256" }],
898
+ stateMutability: "view",
899
+ type: "function"
900
+ },
901
+ {
902
+ inputs: [
903
+ {
904
+ components: [
905
+ { name: "sender", type: "address" },
906
+ { name: "nonce", type: "uint256" },
907
+ { name: "initCode", type: "bytes" },
908
+ { name: "callData", type: "bytes" },
909
+ { name: "accountGasLimits", type: "bytes32" },
910
+ { name: "preVerificationGas", type: "uint256" },
911
+ { name: "gasFees", type: "bytes32" },
912
+ { name: "paymasterAndData", type: "bytes" },
913
+ { name: "signature", type: "bytes" }
914
+ ],
915
+ name: "userOp",
916
+ type: "tuple"
917
+ }
918
+ ],
919
+ name: "getUserOpHash",
920
+ outputs: [{ name: "", type: "bytes32" }],
921
+ stateMutability: "view",
922
+ type: "function"
923
+ }
924
+ ];
925
+ var ACCOUNT_ABI = [
926
+ {
927
+ inputs: [
928
+ {
929
+ components: [
930
+ { name: "sender", type: "address" },
931
+ { name: "nonce", type: "uint256" },
932
+ { name: "initCode", type: "bytes" },
933
+ { name: "callData", type: "bytes" },
934
+ { name: "accountGasLimits", type: "bytes32" },
935
+ { name: "preVerificationGas", type: "uint256" },
936
+ { name: "gasFees", type: "bytes32" },
937
+ { name: "paymasterAndData", type: "bytes" },
938
+ { name: "signature", type: "bytes" }
939
+ ],
940
+ name: "userOp",
941
+ type: "tuple"
942
+ },
943
+ { name: "userOpHash", type: "bytes32" },
944
+ { name: "missingAccountFunds", type: "uint256" }
945
+ ],
946
+ name: "validateUserOp",
947
+ outputs: [{ name: "validationData", type: "uint256" }],
948
+ stateMutability: "nonpayable",
949
+ type: "function"
950
+ },
951
+ {
952
+ inputs: [
953
+ { name: "dest", type: "address" },
954
+ { name: "value", type: "uint256" },
955
+ { name: "func", type: "bytes" }
956
+ ],
957
+ name: "execute",
958
+ outputs: [],
959
+ stateMutability: "nonpayable",
960
+ type: "function"
961
+ },
962
+ {
963
+ inputs: [
964
+ { name: "dest", type: "address[]" },
965
+ { name: "value", type: "uint256[]" },
966
+ { name: "func", type: "bytes[]" }
967
+ ],
968
+ name: "executeBatch",
969
+ outputs: [],
970
+ stateMutability: "nonpayable",
971
+ type: "function"
972
+ }
973
+ ];
974
+ var BUNDLER_METHODS = {
975
+ sendUserOperation: "eth_sendUserOperation",
976
+ estimateUserOperationGas: "eth_estimateUserOperationGas",
977
+ getUserOperationByHash: "eth_getUserOperationByHash",
978
+ getUserOperationReceipt: "eth_getUserOperationReceipt",
979
+ supportedEntryPoints: "eth_supportedEntryPoints",
980
+ chainId: "eth_chainId"
981
+ };
982
+ var PaymasterType = /* @__PURE__ */ ((PaymasterType2) => {
983
+ PaymasterType2["None"] = "none";
984
+ PaymasterType2["Verifying"] = "verifying";
985
+ PaymasterType2["Token"] = "token";
986
+ PaymasterType2["Sponsoring"] = "sponsoring";
987
+ return PaymasterType2;
988
+ })(PaymasterType || {});
989
+ function packAccountGasLimits(verificationGasLimit, callGasLimit) {
990
+ const verificationHex = verificationGasLimit.toString(16).padStart(32, "0");
991
+ const callHex = callGasLimit.toString(16).padStart(32, "0");
992
+ return `0x${verificationHex}${callHex}`;
993
+ }
994
+ function unpackAccountGasLimits(packed) {
995
+ const hex = packed.slice(2);
996
+ const verificationHex = hex.slice(0, 32);
997
+ const callHex = hex.slice(32, 64);
998
+ return {
999
+ verificationGasLimit: BigInt("0x" + verificationHex),
1000
+ callGasLimit: BigInt("0x" + callHex)
1001
+ };
1002
+ }
1003
+ function packGasFees(maxPriorityFeePerGas, maxFeePerGas) {
1004
+ const priorityHex = maxPriorityFeePerGas.toString(16).padStart(32, "0");
1005
+ const maxHex = maxFeePerGas.toString(16).padStart(32, "0");
1006
+ return `0x${priorityHex}${maxHex}`;
1007
+ }
1008
+ function unpackGasFees(packed) {
1009
+ const hex = packed.slice(2);
1010
+ const priorityHex = hex.slice(0, 32);
1011
+ const maxHex = hex.slice(32, 64);
1012
+ return {
1013
+ maxPriorityFeePerGas: BigInt("0x" + priorityHex),
1014
+ maxFeePerGas: BigInt("0x" + maxHex)
1015
+ };
1016
+ }
1017
+
1018
+ // src/erc4337/builder.ts
1019
+ import { concat, pad, toHex } from "viem";
1020
+ var UserOpBuilder = class {
1021
+ constructor(options = {}) {
1022
+ this.entryPoint = options.entryPoint ?? ENTRYPOINT_V07_ADDRESS;
1023
+ this.gasMultiplier = options.gasMultiplier ?? 1.2;
1024
+ }
1025
+ /**
1026
+ * Build a UserOperation from a transaction intent
1027
+ */
1028
+ async buildUserOp(signer, intent, client, gasEstimate, paymaster) {
1029
+ const sender = await signer.getAddress();
1030
+ const nonce = await this.getNonce(client, sender);
1031
+ const isDeployed = await signer.isDeployed();
1032
+ const initCode = isDeployed ? "0x" : await signer.getInitCode();
1033
+ const callData = signer.encodeExecute(
1034
+ intent.to,
1035
+ intent.value ?? 0n,
1036
+ intent.data ?? "0x"
1037
+ );
1038
+ const { maxFeePerGas, maxPriorityFeePerGas } = await this.getGasPrices(client);
1039
+ const gas = gasEstimate ?? DEFAULT_GAS_LIMITS;
1040
+ const verificationGasLimit = this.applyMultiplier(gas.verificationGasLimit);
1041
+ const callGasLimit = this.applyMultiplier(gas.callGasLimit);
1042
+ const preVerificationGas = this.applyMultiplier(gas.preVerificationGas);
1043
+ const paymasterAndData = paymaster ? this.encodePaymasterData(paymaster) : "0x";
1044
+ return {
1045
+ sender,
1046
+ nonce,
1047
+ initCode,
1048
+ callData,
1049
+ verificationGasLimit,
1050
+ callGasLimit,
1051
+ preVerificationGas,
1052
+ maxPriorityFeePerGas,
1053
+ maxFeePerGas,
1054
+ paymasterAndData,
1055
+ signature: "0x"
1056
+ // Will be filled after signing
1057
+ };
1058
+ }
1059
+ /**
1060
+ * Build a batch UserOperation from multiple transaction intents
1061
+ */
1062
+ async buildBatchUserOp(signer, intents, client, gasEstimate, paymaster) {
1063
+ const sender = await signer.getAddress();
1064
+ const nonce = await this.getNonce(client, sender);
1065
+ const isDeployed = await signer.isDeployed();
1066
+ const initCode = isDeployed ? "0x" : await signer.getInitCode();
1067
+ const targets = intents.map((i) => i.to);
1068
+ const values = intents.map((i) => i.value ?? 0n);
1069
+ const datas = intents.map((i) => i.data ?? "0x");
1070
+ const callData = signer.encodeExecuteBatch(targets, values, datas);
1071
+ const { maxFeePerGas, maxPriorityFeePerGas } = await this.getGasPrices(client);
1072
+ const gas = gasEstimate ?? {
1073
+ verificationGasLimit: DEFAULT_GAS_LIMITS.verificationGasLimit,
1074
+ callGasLimit: DEFAULT_GAS_LIMITS.callGasLimit * BigInt(intents.length),
1075
+ preVerificationGas: DEFAULT_GAS_LIMITS.preVerificationGas
1076
+ };
1077
+ const verificationGasLimit = this.applyMultiplier(gas.verificationGasLimit);
1078
+ const callGasLimit = this.applyMultiplier(gas.callGasLimit);
1079
+ const preVerificationGas = this.applyMultiplier(gas.preVerificationGas);
1080
+ const paymasterAndData = paymaster ? this.encodePaymasterData(paymaster) : "0x";
1081
+ return {
1082
+ sender,
1083
+ nonce,
1084
+ initCode,
1085
+ callData,
1086
+ verificationGasLimit,
1087
+ callGasLimit,
1088
+ preVerificationGas,
1089
+ maxPriorityFeePerGas,
1090
+ maxFeePerGas,
1091
+ paymasterAndData,
1092
+ signature: "0x"
1093
+ };
1094
+ }
1095
+ /**
1096
+ * Pack a UserOperation for on-chain submission (v0.7 format)
1097
+ */
1098
+ packUserOp(userOp) {
1099
+ return {
1100
+ sender: userOp.sender,
1101
+ nonce: userOp.nonce,
1102
+ initCode: userOp.initCode,
1103
+ callData: userOp.callData,
1104
+ accountGasLimits: packAccountGasLimits(
1105
+ userOp.verificationGasLimit,
1106
+ userOp.callGasLimit
1107
+ ),
1108
+ preVerificationGas: userOp.preVerificationGas,
1109
+ gasFees: packGasFees(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas),
1110
+ paymasterAndData: userOp.paymasterAndData,
1111
+ signature: userOp.signature
1112
+ };
1113
+ }
1114
+ /**
1115
+ * Compute the UserOperation hash for signing
1116
+ */
1117
+ async getUserOpHash(userOp, client, chainId) {
1118
+ const packed = this.packUserOp(userOp);
1119
+ const userOpTuple = {
1120
+ sender: packed.sender,
1121
+ nonce: packed.nonce,
1122
+ initCode: packed.initCode,
1123
+ callData: packed.callData,
1124
+ accountGasLimits: packed.accountGasLimits,
1125
+ preVerificationGas: packed.preVerificationGas,
1126
+ gasFees: packed.gasFees,
1127
+ paymasterAndData: packed.paymasterAndData,
1128
+ signature: packed.signature
1129
+ };
1130
+ const hash = await client.readContract({
1131
+ address: this.entryPoint,
1132
+ abi: ENTRYPOINT_V07_ABI,
1133
+ functionName: "getUserOpHash",
1134
+ args: [userOpTuple]
1135
+ });
1136
+ return hash;
1137
+ }
1138
+ /**
1139
+ * Sign a UserOperation
1140
+ */
1141
+ async signUserOp(userOp, signer, client, chainId) {
1142
+ const userOpHash = await this.getUserOpHash(userOp, client, chainId);
1143
+ const signature = await signer.signUserOpHash(userOpHash);
1144
+ return {
1145
+ ...userOp,
1146
+ signature
1147
+ };
1148
+ }
1149
+ /**
1150
+ * Get the nonce for an account from EntryPoint
1151
+ */
1152
+ async getNonce(client, sender) {
1153
+ try {
1154
+ const nonce = await client.readContract({
1155
+ address: this.entryPoint,
1156
+ abi: ENTRYPOINT_V07_ABI,
1157
+ functionName: "getNonce",
1158
+ args: [sender, 0n]
1159
+ // Use key 0 for default nonce space
1160
+ });
1161
+ return nonce;
1162
+ } catch {
1163
+ return 0n;
1164
+ }
1165
+ }
1166
+ /**
1167
+ * Get current gas prices from the chain
1168
+ */
1169
+ async getGasPrices(client) {
1170
+ const block = await client.getBlock({ blockTag: "latest" });
1171
+ const baseFee = block.baseFeePerGas ?? 0n;
1172
+ const maxPriorityFeePerGas = 1500000000n;
1173
+ const maxFeePerGas = baseFee * 2n + maxPriorityFeePerGas;
1174
+ return { maxFeePerGas, maxPriorityFeePerGas };
1175
+ }
1176
+ /**
1177
+ * Apply gas multiplier for safety margin
1178
+ */
1179
+ applyMultiplier(gas) {
1180
+ return BigInt(Math.ceil(Number(gas) * this.gasMultiplier));
1181
+ }
1182
+ /**
1183
+ * Encode paymaster data for the UserOperation
1184
+ */
1185
+ encodePaymasterData(paymaster) {
1186
+ const paymasterAddress = paymaster.paymaster;
1187
+ const verificationGas = pad(toHex(paymaster.paymasterVerificationGasLimit), {
1188
+ size: 16
1189
+ });
1190
+ const postOpGas = pad(toHex(paymaster.paymasterPostOpGasLimit), { size: 16 });
1191
+ return concat([
1192
+ paymasterAddress,
1193
+ verificationGas,
1194
+ postOpGas,
1195
+ paymaster.paymasterData
1196
+ ]);
1197
+ }
1198
+ };
1199
+ function createUserOpBuilder(options) {
1200
+ return new UserOpBuilder(options);
1201
+ }
1202
+
1203
+ // src/erc4337/bundler.ts
1204
+ var BundlerError = class extends Error {
1205
+ constructor(message, code, data) {
1206
+ super(message);
1207
+ this.code = code;
1208
+ this.data = data;
1209
+ this.name = "BundlerError";
1210
+ }
1211
+ };
1212
+ var BundlerClient = class {
1213
+ constructor(config) {
1214
+ this.requestId = 0;
1215
+ this.bundlerUrl = config.bundlerUrl;
1216
+ this.entryPoint = config.entryPoint ?? ENTRYPOINT_V07_ADDRESS;
1217
+ this.chainId = config.chainId;
1218
+ }
1219
+ /**
1220
+ * Send a UserOperation to the bundler
1221
+ */
1222
+ async sendUserOperation(userOp) {
1223
+ const packed = this.packForRpc(userOp);
1224
+ const userOpHash = await this.rpcCall(
1225
+ BUNDLER_METHODS.sendUserOperation,
1226
+ [packed, this.entryPoint]
1227
+ );
1228
+ return {
1229
+ userOpHash,
1230
+ wait: () => this.waitForReceipt(userOpHash)
1231
+ };
1232
+ }
1233
+ /**
1234
+ * Estimate gas for a UserOperation
1235
+ */
1236
+ async estimateUserOperationGas(userOp) {
1237
+ const estimationOp = {
1238
+ sender: userOp.sender,
1239
+ nonce: userOp.nonce ?? 0n,
1240
+ initCode: userOp.initCode ?? "0x",
1241
+ callData: userOp.callData,
1242
+ verificationGasLimit: userOp.verificationGasLimit ?? 1000000n,
1243
+ callGasLimit: userOp.callGasLimit ?? 1000000n,
1244
+ preVerificationGas: userOp.preVerificationGas ?? 100000n,
1245
+ maxPriorityFeePerGas: userOp.maxPriorityFeePerGas ?? 1000000000n,
1246
+ maxFeePerGas: userOp.maxFeePerGas ?? 10000000000n,
1247
+ paymasterAndData: userOp.paymasterAndData ?? "0x",
1248
+ signature: userOp.signature ?? // Dummy signature for estimation
1249
+ "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"
1250
+ };
1251
+ const packed = this.packForRpc(estimationOp);
1252
+ const result = await this.rpcCall(BUNDLER_METHODS.estimateUserOperationGas, [packed, this.entryPoint]);
1253
+ return {
1254
+ verificationGasLimit: BigInt(result.verificationGasLimit),
1255
+ callGasLimit: BigInt(result.callGasLimit),
1256
+ preVerificationGas: BigInt(result.preVerificationGas),
1257
+ paymasterVerificationGasLimit: result.paymasterVerificationGasLimit ? BigInt(result.paymasterVerificationGasLimit) : void 0,
1258
+ paymasterPostOpGasLimit: result.paymasterPostOpGasLimit ? BigInt(result.paymasterPostOpGasLimit) : void 0
1259
+ };
1260
+ }
1261
+ /**
1262
+ * Get UserOperation by hash
1263
+ */
1264
+ async getUserOperationByHash(userOpHash) {
1265
+ const result = await this.rpcCall(BUNDLER_METHODS.getUserOperationByHash, [userOpHash]);
1266
+ return result;
1267
+ }
1268
+ /**
1269
+ * Get UserOperation receipt
1270
+ */
1271
+ async getUserOperationReceipt(userOpHash) {
1272
+ const result = await this.rpcCall(BUNDLER_METHODS.getUserOperationReceipt, [userOpHash]);
1273
+ if (!result) return null;
1274
+ return {
1275
+ userOpHash: result.userOpHash,
1276
+ sender: result.sender,
1277
+ nonce: BigInt(result.nonce),
1278
+ paymaster: result.paymaster,
1279
+ actualGasCost: BigInt(result.actualGasCost),
1280
+ actualGasUsed: BigInt(result.actualGasUsed),
1281
+ success: result.success,
1282
+ reason: result.reason,
1283
+ receipt: {
1284
+ transactionHash: result.receipt.transactionHash,
1285
+ blockNumber: BigInt(result.receipt.blockNumber),
1286
+ blockHash: result.receipt.blockHash
1287
+ }
1288
+ };
1289
+ }
1290
+ /**
1291
+ * Get supported EntryPoints
1292
+ */
1293
+ async getSupportedEntryPoints() {
1294
+ return this.rpcCall(BUNDLER_METHODS.supportedEntryPoints, []);
1295
+ }
1296
+ /**
1297
+ * Get chain ID from bundler
1298
+ */
1299
+ async getChainId() {
1300
+ const result = await this.rpcCall(BUNDLER_METHODS.chainId, []);
1301
+ return Number(result);
1302
+ }
1303
+ /**
1304
+ * Wait for UserOperation receipt with polling
1305
+ */
1306
+ async waitForReceipt(userOpHash, options = {}) {
1307
+ const timeout = options.timeout ?? 6e4;
1308
+ const pollingInterval = options.pollingInterval ?? 2e3;
1309
+ const startTime = Date.now();
1310
+ while (Date.now() - startTime < timeout) {
1311
+ const receipt = await this.getUserOperationReceipt(userOpHash);
1312
+ if (receipt) {
1313
+ return receipt;
1314
+ }
1315
+ await new Promise((resolve) => setTimeout(resolve, pollingInterval));
1316
+ }
1317
+ throw new BundlerError(
1318
+ `Timeout waiting for UserOperation receipt: ${userOpHash}`
1319
+ );
1320
+ }
1321
+ /**
1322
+ * Pack UserOperation for RPC (convert bigints to hex strings)
1323
+ */
1324
+ packForRpc(userOp) {
1325
+ return {
1326
+ sender: userOp.sender,
1327
+ nonce: this.toHex(userOp.nonce),
1328
+ initCode: userOp.initCode,
1329
+ callData: userOp.callData,
1330
+ accountGasLimits: packAccountGasLimits(
1331
+ userOp.verificationGasLimit,
1332
+ userOp.callGasLimit
1333
+ ),
1334
+ preVerificationGas: this.toHex(userOp.preVerificationGas),
1335
+ gasFees: packGasFees(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas),
1336
+ paymasterAndData: userOp.paymasterAndData,
1337
+ signature: userOp.signature
1338
+ };
1339
+ }
1340
+ /**
1341
+ * Convert bigint to hex string
1342
+ */
1343
+ toHex(value) {
1344
+ return `0x${value.toString(16)}`;
1345
+ }
1346
+ /**
1347
+ * Make a JSON-RPC call to the bundler
1348
+ */
1349
+ async rpcCall(method, params) {
1350
+ const request = {
1351
+ jsonrpc: "2.0",
1352
+ id: ++this.requestId,
1353
+ method,
1354
+ params
1355
+ };
1356
+ const response = await fetch(this.bundlerUrl, {
1357
+ method: "POST",
1358
+ headers: {
1359
+ "Content-Type": "application/json"
1360
+ },
1361
+ body: JSON.stringify(request)
1362
+ });
1363
+ if (!response.ok) {
1364
+ throw new BundlerError(
1365
+ `HTTP error: ${response.status} ${response.statusText}`
1366
+ );
1367
+ }
1368
+ const json = await response.json();
1369
+ if (json.error) {
1370
+ throw new BundlerError(json.error.message, json.error.code, json.error.data);
1371
+ }
1372
+ return json.result;
1373
+ }
1374
+ };
1375
+ function createBundlerClient(config) {
1376
+ return new BundlerClient(config);
1377
+ }
1378
+
1379
+ // src/erc4337/paymaster.ts
1380
+ import { concat as concat2, pad as pad2, toHex as toHex2 } from "viem";
1381
+ var PaymasterClient = class {
1382
+ constructor(config) {
1383
+ this.config = config;
1384
+ }
1385
+ /**
1386
+ * Get paymaster data for a UserOperation
1387
+ */
1388
+ async getPaymasterData(userOp, chainId, entryPoint, context) {
1389
+ switch (this.config.type) {
1390
+ case "verifying":
1391
+ return this.getVerifyingPaymasterData(userOp, chainId, entryPoint);
1392
+ case "sponsoring":
1393
+ return this.getSponsoringPaymasterData(
1394
+ userOp,
1395
+ chainId,
1396
+ entryPoint,
1397
+ context
1398
+ );
1399
+ case "token":
1400
+ return this.getTokenPaymasterData(userOp, chainId, entryPoint);
1401
+ default:
1402
+ throw new Error(`Unknown paymaster type: ${this.config.type}`);
1403
+ }
1404
+ }
1405
+ /**
1406
+ * Get gas estimates including paymaster gas
1407
+ */
1408
+ async estimatePaymasterGas(userOp, _chainId) {
1409
+ return {
1410
+ verificationGasLimit: DEFAULT_GAS_LIMITS.verificationGasLimit,
1411
+ callGasLimit: DEFAULT_GAS_LIMITS.callGasLimit,
1412
+ preVerificationGas: DEFAULT_GAS_LIMITS.preVerificationGas,
1413
+ paymasterVerificationGasLimit: DEFAULT_GAS_LIMITS.paymasterVerificationGasLimit,
1414
+ paymasterPostOpGasLimit: DEFAULT_GAS_LIMITS.paymasterPostOpGasLimit
1415
+ };
1416
+ }
1417
+ /**
1418
+ * Check if the paymaster will sponsor this operation
1419
+ */
1420
+ async willSponsor(userOp, chainId, entryPoint, context) {
1421
+ if (!this.config.url) {
1422
+ return true;
1423
+ }
1424
+ try {
1425
+ const response = await fetch(`${this.config.url}/check`, {
1426
+ method: "POST",
1427
+ headers: { "Content-Type": "application/json" },
1428
+ body: JSON.stringify({
1429
+ userOp: this.serializeUserOp(userOp),
1430
+ chainId,
1431
+ entryPoint,
1432
+ context
1433
+ })
1434
+ });
1435
+ if (!response.ok) return false;
1436
+ const result = await response.json();
1437
+ return result.willSponsor;
1438
+ } catch {
1439
+ return false;
1440
+ }
1441
+ }
1442
+ /**
1443
+ * Get verifying paymaster data (off-chain signature)
1444
+ */
1445
+ async getVerifyingPaymasterData(userOp, chainId, entryPoint) {
1446
+ if (this.config.url) {
1447
+ return this.callPaymasterService(userOp, chainId, entryPoint);
1448
+ }
1449
+ return {
1450
+ paymaster: this.config.address,
1451
+ paymasterVerificationGasLimit: DEFAULT_GAS_LIMITS.paymasterVerificationGasLimit,
1452
+ paymasterPostOpGasLimit: DEFAULT_GAS_LIMITS.paymasterPostOpGasLimit,
1453
+ paymasterData: "0x"
1454
+ };
1455
+ }
1456
+ /**
1457
+ * Get sponsoring paymaster data (third-party pays)
1458
+ */
1459
+ async getSponsoringPaymasterData(userOp, chainId, entryPoint, context) {
1460
+ if (!this.config.url) {
1461
+ throw new Error("Sponsoring paymaster requires a service URL");
1462
+ }
1463
+ const response = await fetch(`${this.config.url}/sponsor`, {
1464
+ method: "POST",
1465
+ headers: { "Content-Type": "application/json" },
1466
+ body: JSON.stringify({
1467
+ userOp: this.serializeUserOp(userOp),
1468
+ chainId,
1469
+ entryPoint,
1470
+ context
1471
+ })
1472
+ });
1473
+ if (!response.ok) {
1474
+ const error = await response.text();
1475
+ throw new Error(`Paymaster rejected sponsorship: ${error}`);
1476
+ }
1477
+ const result = await response.json();
1478
+ return {
1479
+ paymaster: result.paymaster,
1480
+ paymasterVerificationGasLimit: result.paymasterVerificationGasLimit,
1481
+ paymasterPostOpGasLimit: result.paymasterPostOpGasLimit,
1482
+ paymasterData: result.paymasterData
1483
+ };
1484
+ }
1485
+ /**
1486
+ * Get token paymaster data (pay gas with ERC20)
1487
+ */
1488
+ async getTokenPaymasterData(userOp, chainId, entryPoint) {
1489
+ const tokenAddress = this.config.options?.tokenAddress;
1490
+ if (!tokenAddress) {
1491
+ throw new Error("Token paymaster requires tokenAddress in options");
1492
+ }
1493
+ if (this.config.url) {
1494
+ return this.callPaymasterService(userOp, chainId, entryPoint, {
1495
+ tokenAddress
1496
+ });
1497
+ }
1498
+ return {
1499
+ paymaster: this.config.address,
1500
+ paymasterVerificationGasLimit: DEFAULT_GAS_LIMITS.paymasterVerificationGasLimit,
1501
+ paymasterPostOpGasLimit: DEFAULT_GAS_LIMITS.paymasterPostOpGasLimit,
1502
+ paymasterData: tokenAddress
1503
+ // Token address as data
1504
+ };
1505
+ }
1506
+ /**
1507
+ * Call paymaster service API
1508
+ */
1509
+ async callPaymasterService(userOp, chainId, entryPoint, context) {
1510
+ if (!this.config.url) {
1511
+ throw new Error("Paymaster service URL not configured");
1512
+ }
1513
+ const response = await fetch(`${this.config.url}/getPaymasterData`, {
1514
+ method: "POST",
1515
+ headers: { "Content-Type": "application/json" },
1516
+ body: JSON.stringify({
1517
+ userOp: this.serializeUserOp(userOp),
1518
+ chainId,
1519
+ entryPoint,
1520
+ context
1521
+ })
1522
+ });
1523
+ if (!response.ok) {
1524
+ const error = await response.text();
1525
+ throw new Error(`Paymaster service error: ${error}`);
1526
+ }
1527
+ const result = await response.json();
1528
+ return {
1529
+ paymaster: result.paymaster,
1530
+ paymasterVerificationGasLimit: BigInt(result.paymasterVerificationGasLimit),
1531
+ paymasterPostOpGasLimit: BigInt(result.paymasterPostOpGasLimit),
1532
+ paymasterData: result.paymasterData
1533
+ };
1534
+ }
1535
+ /**
1536
+ * Serialize UserOperation for API calls
1537
+ */
1538
+ serializeUserOp(userOp) {
1539
+ const result = {};
1540
+ if (userOp.sender) result.sender = userOp.sender;
1541
+ if (userOp.nonce !== void 0)
1542
+ result.nonce = `0x${userOp.nonce.toString(16)}`;
1543
+ if (userOp.initCode) result.initCode = userOp.initCode;
1544
+ if (userOp.callData) result.callData = userOp.callData;
1545
+ if (userOp.verificationGasLimit !== void 0)
1546
+ result.verificationGasLimit = `0x${userOp.verificationGasLimit.toString(16)}`;
1547
+ if (userOp.callGasLimit !== void 0)
1548
+ result.callGasLimit = `0x${userOp.callGasLimit.toString(16)}`;
1549
+ if (userOp.preVerificationGas !== void 0)
1550
+ result.preVerificationGas = `0x${userOp.preVerificationGas.toString(16)}`;
1551
+ if (userOp.maxPriorityFeePerGas !== void 0)
1552
+ result.maxPriorityFeePerGas = `0x${userOp.maxPriorityFeePerGas.toString(16)}`;
1553
+ if (userOp.maxFeePerGas !== void 0)
1554
+ result.maxFeePerGas = `0x${userOp.maxFeePerGas.toString(16)}`;
1555
+ if (userOp.paymasterAndData) result.paymasterAndData = userOp.paymasterAndData;
1556
+ if (userOp.signature) result.signature = userOp.signature;
1557
+ return result;
1558
+ }
1559
+ };
1560
+ function createPaymasterClient(config) {
1561
+ return new PaymasterClient(config);
1562
+ }
1563
+ function encodePaymasterAndData(data) {
1564
+ return concat2([
1565
+ data.paymaster,
1566
+ pad2(toHex2(data.paymasterVerificationGasLimit), { size: 16 }),
1567
+ pad2(toHex2(data.paymasterPostOpGasLimit), { size: 16 }),
1568
+ data.paymasterData
1569
+ ]);
1570
+ }
1571
+ function decodePaymasterAndData(paymasterAndData) {
1572
+ if (paymasterAndData === "0x" || paymasterAndData.length < 86) {
1573
+ return null;
1574
+ }
1575
+ const paymaster = `0x${paymasterAndData.slice(2, 42)}`;
1576
+ const paymasterVerificationGasLimit = BigInt(
1577
+ `0x${paymasterAndData.slice(42, 74)}`
1578
+ );
1579
+ const paymasterPostOpGasLimit = BigInt(`0x${paymasterAndData.slice(74, 106)}`);
1580
+ const paymasterData = `0x${paymasterAndData.slice(106)}`;
1581
+ return {
1582
+ paymaster,
1583
+ paymasterVerificationGasLimit,
1584
+ paymasterPostOpGasLimit,
1585
+ paymasterData
1586
+ };
1587
+ }
1588
+
1589
+ // src/erc4337/t402.ts
1590
+ import { encodeFunctionData as encodeFunctionData2 } from "viem";
1591
+ var ERC20_TRANSFER_ABI = [
1592
+ {
1593
+ inputs: [
1594
+ { name: "to", type: "address" },
1595
+ { name: "amount", type: "uint256" }
1596
+ ],
1597
+ name: "transfer",
1598
+ outputs: [{ name: "", type: "bool" }],
1599
+ stateMutability: "nonpayable",
1600
+ type: "function"
1601
+ }
1602
+ ];
1603
+ var EIP3009_TRANSFER_ABI = [
1604
+ {
1605
+ inputs: [
1606
+ { name: "from", type: "address" },
1607
+ { name: "to", type: "address" },
1608
+ { name: "value", type: "uint256" },
1609
+ { name: "validAfter", type: "uint256" },
1610
+ { name: "validBefore", type: "uint256" },
1611
+ { name: "nonce", type: "bytes32" },
1612
+ { name: "v", type: "uint8" },
1613
+ { name: "r", type: "bytes32" },
1614
+ { name: "s", type: "bytes32" }
1615
+ ],
1616
+ name: "transferWithAuthorization",
1617
+ outputs: [],
1618
+ stateMutability: "nonpayable",
1619
+ type: "function"
1620
+ }
1621
+ ];
1622
+ var GaslessT402Client = class {
1623
+ constructor(config) {
1624
+ this.signer = config.signer;
1625
+ this.builder = new UserOpBuilder();
1626
+ this.bundler = new BundlerClient(config.bundler);
1627
+ this.paymaster = config.paymaster ? new PaymasterClient(config.paymaster) : void 0;
1628
+ this.chainId = config.chainId;
1629
+ this.publicClient = config.publicClient;
1630
+ }
1631
+ /**
1632
+ * Execute a T402 payment via ERC-4337
1633
+ *
1634
+ * This submits the payment as a UserOperation which can be:
1635
+ * - Sponsored by a paymaster (truly gasless)
1636
+ * - Paid from the smart account's balance
1637
+ */
1638
+ async executePayment(params) {
1639
+ const callData = params.authorization ? this.buildAuthorizedTransferCallData(params) : this.buildTransferCallData(params);
1640
+ const intent = {
1641
+ to: params.tokenAddress,
1642
+ value: 0n,
1643
+ data: callData
1644
+ };
1645
+ const gasEstimate = await this.estimateGas(intent);
1646
+ const paymasterData = await this.getPaymasterData(gasEstimate);
1647
+ const userOp = await this.builder.buildUserOp(
1648
+ this.signer,
1649
+ intent,
1650
+ this.publicClient,
1651
+ gasEstimate,
1652
+ paymasterData
1653
+ );
1654
+ const signedUserOp = await this.builder.signUserOp(
1655
+ userOp,
1656
+ this.signer,
1657
+ this.publicClient,
1658
+ this.chainId
1659
+ );
1660
+ return this.bundler.sendUserOperation(signedUserOp);
1661
+ }
1662
+ /**
1663
+ * Execute multiple T402 payments in a single UserOperation
1664
+ */
1665
+ async executeBatchPayments(payments) {
1666
+ const intents = payments.map((params) => ({
1667
+ to: params.tokenAddress,
1668
+ value: 0n,
1669
+ data: params.authorization ? this.buildAuthorizedTransferCallData(params) : this.buildTransferCallData(params)
1670
+ }));
1671
+ const gasEstimate = await this.estimateBatchGas(intents);
1672
+ const paymasterData = await this.getPaymasterData(gasEstimate);
1673
+ const userOp = await this.builder.buildBatchUserOp(
1674
+ this.signer,
1675
+ intents,
1676
+ this.publicClient,
1677
+ gasEstimate,
1678
+ paymasterData
1679
+ );
1680
+ const signedUserOp = await this.builder.signUserOp(
1681
+ userOp,
1682
+ this.signer,
1683
+ this.publicClient,
1684
+ this.chainId
1685
+ );
1686
+ return this.bundler.sendUserOperation(signedUserOp);
1687
+ }
1688
+ /**
1689
+ * Check if a payment can be sponsored (gasless)
1690
+ */
1691
+ async canSponsor(params) {
1692
+ if (!this.paymaster) return false;
1693
+ const intent = {
1694
+ to: params.tokenAddress,
1695
+ value: 0n,
1696
+ data: this.buildTransferCallData(params)
1697
+ };
1698
+ const sender = await this.signer.getAddress();
1699
+ return this.paymaster.willSponsor(
1700
+ { sender, callData: this.signer.encodeExecute(intent.to, 0n, intent.data) },
1701
+ this.chainId,
1702
+ ENTRYPOINT_V07_ADDRESS
1703
+ );
1704
+ }
1705
+ /**
1706
+ * Get the smart account address
1707
+ */
1708
+ async getAccountAddress() {
1709
+ return this.signer.getAddress();
1710
+ }
1711
+ /**
1712
+ * Check if the smart account is deployed
1713
+ */
1714
+ async isAccountDeployed() {
1715
+ return this.signer.isDeployed();
1716
+ }
1717
+ /**
1718
+ * Build call data for a simple ERC20 transfer
1719
+ */
1720
+ buildTransferCallData(params) {
1721
+ return encodeFunctionData2({
1722
+ abi: ERC20_TRANSFER_ABI,
1723
+ functionName: "transfer",
1724
+ args: [params.to, params.amount]
1725
+ });
1726
+ }
1727
+ /**
1728
+ * Build call data for an authorized transfer (EIP-3009)
1729
+ */
1730
+ buildAuthorizedTransferCallData(params) {
1731
+ if (!params.authorization) {
1732
+ throw new Error("Authorization required for authorized transfer");
1733
+ }
1734
+ const sig = params.authorization.signature;
1735
+ const r = `0x${sig.slice(2, 66)}`;
1736
+ const s = `0x${sig.slice(66, 130)}`;
1737
+ const v = parseInt(sig.slice(130, 132), 16);
1738
+ return encodeFunctionData2({
1739
+ abi: EIP3009_TRANSFER_ABI,
1740
+ functionName: "transferWithAuthorization",
1741
+ args: [
1742
+ params.to,
1743
+ // from (will be overwritten by smart account)
1744
+ params.to,
1745
+ params.amount,
1746
+ params.authorization.validAfter,
1747
+ params.authorization.validBefore,
1748
+ params.authorization.nonce,
1749
+ v,
1750
+ r,
1751
+ s
1752
+ ]
1753
+ });
1754
+ }
1755
+ /**
1756
+ * Estimate gas for a single transaction
1757
+ */
1758
+ async estimateGas(intent) {
1759
+ const sender = await this.signer.getAddress();
1760
+ const callData = this.signer.encodeExecute(
1761
+ intent.to,
1762
+ intent.value ?? 0n,
1763
+ intent.data ?? "0x"
1764
+ );
1765
+ try {
1766
+ return await this.bundler.estimateUserOperationGas({
1767
+ sender,
1768
+ callData
1769
+ });
1770
+ } catch {
1771
+ return {
1772
+ verificationGasLimit: 150000n,
1773
+ callGasLimit: 100000n,
1774
+ preVerificationGas: 50000n
1775
+ };
1776
+ }
1777
+ }
1778
+ /**
1779
+ * Estimate gas for a batch transaction
1780
+ */
1781
+ async estimateBatchGas(intents) {
1782
+ const sender = await this.signer.getAddress();
1783
+ const callData = this.signer.encodeExecuteBatch(
1784
+ intents.map((i) => i.to),
1785
+ intents.map((i) => i.value ?? 0n),
1786
+ intents.map((i) => i.data ?? "0x")
1787
+ );
1788
+ try {
1789
+ return await this.bundler.estimateUserOperationGas({
1790
+ sender,
1791
+ callData
1792
+ });
1793
+ } catch {
1794
+ return {
1795
+ verificationGasLimit: 150000n,
1796
+ callGasLimit: 100000n * BigInt(intents.length),
1797
+ preVerificationGas: 50000n
1798
+ };
1799
+ }
1800
+ }
1801
+ /**
1802
+ * Get paymaster data if configured
1803
+ */
1804
+ async getPaymasterData(_gasEstimate) {
1805
+ if (!this.paymaster) return void 0;
1806
+ const sender = await this.signer.getAddress();
1807
+ return this.paymaster.getPaymasterData(
1808
+ { sender },
1809
+ this.chainId,
1810
+ ENTRYPOINT_V07_ADDRESS
1811
+ );
1812
+ }
1813
+ };
1814
+ function createGaslessT402Client(config) {
1815
+ return new GaslessT402Client(config);
1816
+ }
1817
+ export {
1818
+ ACCOUNT_ABI,
1819
+ BUNDLER_METHODS,
1820
+ BundlerClient,
1821
+ BundlerError,
1822
+ DEFAULT_GAS_LIMITS,
1823
+ ENTRYPOINT_V06_ADDRESS,
1824
+ ENTRYPOINT_V07_ABI,
1825
+ ENTRYPOINT_V07_ADDRESS,
1826
+ ExactEvmScheme,
1827
+ ExactLegacyEvmScheme as ExactLegacyEvmClientScheme,
1828
+ ExactLegacyEvmScheme3 as ExactLegacyEvmFacilitatorScheme,
1829
+ ExactLegacyEvmScheme2 as ExactLegacyEvmServerScheme,
1830
+ GaslessT402Client,
1831
+ LAYERZERO_ENDPOINT_IDS,
1832
+ LAYERZERO_ENDPOINT_V2,
1833
+ PaymasterClient,
1834
+ PaymasterType,
1835
+ TOKEN_PRIORITY,
1836
+ TOKEN_REGISTRY,
1837
+ USDC_ADDRESSES,
1838
+ USDT0_ADDRESSES,
1839
+ USDT0_OFT_ADDRESSES,
1840
+ USDT_LEGACY_ADDRESSES,
1841
+ Usdt0Bridge,
1842
+ UserOpBuilder,
1843
+ addressToBytes32,
1844
+ authorizationTypes,
1845
+ bytes32ToAddress,
1846
+ createBundlerClient,
1847
+ createGaslessT402Client,
1848
+ createPaymasterClient,
1849
+ createUsdt0Bridge,
1850
+ createUserOpBuilder,
1851
+ decodePaymasterAndData,
1852
+ eip3009ABI,
1853
+ encodePaymasterAndData,
1854
+ erc20LegacyABI,
1855
+ getBridgeableChains,
1856
+ getDefaultToken,
1857
+ getEIP712Domain,
1858
+ getEndpointId,
1859
+ getNetworkTokens,
1860
+ getNetworksForToken,
1861
+ getTokenByAddress,
1862
+ getTokenConfig,
1863
+ getUsdt0Networks,
1864
+ getUsdt0OftAddress,
1865
+ legacyAuthorizationTypes,
1866
+ packAccountGasLimits,
1867
+ packGasFees,
1868
+ supportsBridging,
1869
+ supportsEIP3009,
1870
+ toClientEvmSigner,
1871
+ toFacilitatorEvmSigner,
1872
+ unpackAccountGasLimits,
1873
+ unpackGasFees
1874
+ };
1875
+ //# sourceMappingURL=index.mjs.map