@appliedblockchain/silentdatarollup-core 1.0.9 → 1.0.10

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.
@@ -1,771 +0,0 @@
1
- // src/Base.ts
2
- import debug2 from "debug";
3
- import {
4
- getBytes,
5
- keccak256 as keccak2563,
6
- toUtf8Bytes as toUtf8Bytes3,
7
- TypedDataEncoder
8
- } from "ethers";
9
-
10
- // src/constants.ts
11
- import { keccak256, toUtf8Bytes } from "ethers";
12
- var SIGN_RPC_METHODS = [
13
- "eth_estimateGas",
14
- "eth_getProof",
15
- "eth_getTransactionByHash",
16
- "eth_getTransactionReceipt",
17
- "eth_getUserOperationReceipt",
18
- "eth_getUserOperationByHash"
19
- ];
20
- var eip721Domain = {
21
- name: "Silent Data [Rollup]",
22
- version: "1"
23
- };
24
- var delegateEIP721Types = {
25
- Ticket: [
26
- { name: "expires", type: "string" },
27
- { name: "ephemeralAddress", type: "string" }
28
- ]
29
- };
30
- var DEBUG_NAMESPACE = "silentdata:core";
31
- var DEBUG_NAMESPACE_SILENTDATA_INTERCEPTOR = "silentdata:interceptor";
32
- var HEADER_SIGNATURE = "x-signature";
33
- var HEADER_TIMESTAMP = "x-timestamp";
34
- var HEADER_SIGNATURE_TYPE = "x-signature-type";
35
- var HEADER_EIP712_SIGNATURE = "x-eip712-signature";
36
- var HEADER_DELEGATE = "x-delegate";
37
- var HEADER_DELEGATE_SIGNATURE = "x-delegate-signature";
38
- var HEADER_EIP712_DELEGATE_SIGNATURE = "x-eip712-delegate-signature";
39
- var HEADER_SIGNER_SWC = "x-signer-swc";
40
- var HEADER_FROM_BLOCK = "x-from-block";
41
- var ENTRYPOINT_ADDRESS = "0x34F5Bda45f2Ce00B646BD6B19D0F9817b5D8D398";
42
- var DEFAULT_USER_OPERATION_RECEIPT_LOOKUP_RANGE = 1024;
43
- var USER_OPERATION_EVENT_SIGNATURE = "UserOperationEvent(bytes32,address,address,uint256,bool,uint256,uint256)";
44
- var USER_OPERATION_EVENT_HASH = keccak256(
45
- toUtf8Bytes(USER_OPERATION_EVENT_SIGNATURE)
46
- );
47
- var DEFAULT_DELEGATE_EXPIRES = 10 * 60 * 60;
48
- var DELEGATE_EXPIRATION_THRESHOLD_BUFFER = 5;
49
- var WHITELISTED_METHODS = [
50
- "eth_blockNumber",
51
- "eth_call",
52
- "eth_chainId",
53
- "eth_estimateGas",
54
- "eth_feeHistory",
55
- "eth_gasPrice",
56
- "eth_getBalance",
57
- "eth_getBlockByHash",
58
- "eth_getBlockByNumber",
59
- "eth_getCode",
60
- "eth_getFilterChanges",
61
- "eth_getFilterLogs",
62
- "eth_getHeaderByHash",
63
- "eth_getLogs",
64
- "eth_getProof",
65
- "eth_getTransactionByHash",
66
- "eth_getTransactionCount",
67
- "eth_getTransactionReceipt",
68
- "eth_maxPriorityFeePerGas",
69
- "eth_newBlockFilter",
70
- "eth_sendRawTransaction",
71
- "eth_syncing",
72
- "eth_newFilter",
73
- "eth_newPendingTransactionFilter",
74
- "net_listening",
75
- "net_version",
76
- "net_peerCount",
77
- "web3_clientVersion",
78
- "web3_sha3"
79
- ];
80
-
81
- // src/privateEvents.ts
82
- import { keccak256 as keccak2562, toUtf8Bytes as toUtf8Bytes2 } from "ethers";
83
- var PRIVATE_EVENT_SIGNATURE = "PrivateEvent(address[],bytes32,bytes)";
84
- var PRIVATE_EVENT_SIGNATURE_HASH = keccak2562(
85
- toUtf8Bytes2(PRIVATE_EVENT_SIGNATURE)
86
- );
87
- function calculateEventTypeHash(eventSignature) {
88
- return keccak2562(toUtf8Bytes2(eventSignature));
89
- }
90
-
91
- // src/types.ts
92
- var ChainId = /* @__PURE__ */ ((ChainId2) => {
93
- ChainId2[ChainId2["MAINNET"] = 380929] = "MAINNET";
94
- ChainId2[ChainId2["TESTNET"] = 381185] = "TESTNET";
95
- return ChainId2;
96
- })(ChainId || {});
97
- var NetworkName = /* @__PURE__ */ ((NetworkName2) => {
98
- NetworkName2["MAINNET"] = "sdr";
99
- NetworkName2["TESTNET"] = "sdr-testnet";
100
- return NetworkName2;
101
- })(NetworkName || {});
102
- var SignatureType = /* @__PURE__ */ ((SignatureType2) => {
103
- SignatureType2["Raw"] = "RAW";
104
- SignatureType2["EIP191"] = "EIP191";
105
- SignatureType2["EIP712"] = "EIP712";
106
- return SignatureType2;
107
- })(SignatureType || {});
108
-
109
- // src/utils.ts
110
- import debug from "debug";
111
- import { Wallet } from "ethers";
112
- var log = debug(DEBUG_NAMESPACE);
113
- function getAuthEIP721Types(payload) {
114
- return {
115
- Call: [
116
- {
117
- name: "request",
118
- type: Array.isArray(payload) ? "JsonRPCRequest[]" : "JsonRPCRequest"
119
- },
120
- { name: "timestamp", type: "string" }
121
- ],
122
- JsonRPCRequest: [
123
- { name: "jsonrpc", type: "string" },
124
- { name: "method", type: "string" },
125
- { name: "params", type: "string" },
126
- { name: "id", type: "uint256" }
127
- ]
128
- };
129
- }
130
- async function signAuthHeaderTypedData(signer, payload, timestamp, chainId) {
131
- log("Preparing payload for signTypedData");
132
- const preparePayload = (p) => ({
133
- ...p,
134
- params: JSON.stringify(p.params)
135
- });
136
- const preparedPayload = Array.isArray(payload) ? payload.map(preparePayload) : preparePayload(payload);
137
- const message = {
138
- request: preparedPayload,
139
- timestamp
140
- };
141
- const types = getAuthEIP721Types(payload);
142
- const domain = { ...eip721Domain, chainId };
143
- log("Signing typed data", JSON.stringify({ domain, types, message }, null, 2));
144
- const signature = await signer.signTypedData(domain, types, message);
145
- log("Signature generated:", signature);
146
- return signature;
147
- }
148
- async function signAuthHeaderRawMessage(signer, payload, timestamp, chainId) {
149
- log("Preparing raw message for signing");
150
- const serialRequest = JSON.stringify(payload);
151
- const xMessage = chainId + serialRequest + timestamp;
152
- log("Raw message:", xMessage);
153
- const signature = await signer.signMessage(xMessage);
154
- log("Raw signature generated:", signature);
155
- return signature;
156
- }
157
- async function getAuthHeaders(signer, payload, chainId, signatureType) {
158
- const xTimestamp = (/* @__PURE__ */ new Date()).toISOString();
159
- const headers = {
160
- [HEADER_TIMESTAMP]: xTimestamp
161
- };
162
- switch (signatureType) {
163
- case "RAW" /* Raw */:
164
- log("Generating raw signature");
165
- headers[HEADER_SIGNATURE] = await signAuthHeaderRawMessage(
166
- signer,
167
- payload,
168
- xTimestamp,
169
- chainId
170
- );
171
- break;
172
- case "EIP712" /* EIP712 */:
173
- log("Generating EIP712 signature");
174
- headers[HEADER_EIP712_SIGNATURE] = await signAuthHeaderTypedData(
175
- signer,
176
- payload,
177
- xTimestamp,
178
- chainId
179
- );
180
- break;
181
- default:
182
- throw new Error(`Unsupported signature type: ${signatureType}`);
183
- }
184
- return headers;
185
- }
186
- function isSignableContractCall(payload, contracts) {
187
- if (!contracts || contracts.length === 0) {
188
- return false;
189
- }
190
- log("Checking if contract call is signable");
191
- if (payload.method !== "eth_call") {
192
- log("Payload method is not eth_call, returning false");
193
- return false;
194
- }
195
- const params = payload.params;
196
- if (!params || params.length === 0 || typeof params[0] !== "object") {
197
- log("Invalid params, returning false");
198
- return false;
199
- }
200
- const callTarget = params[0].to;
201
- if (!callTarget) {
202
- log("Missing call target, returning false");
203
- return false;
204
- }
205
- log(`Call target: ${callTarget}`);
206
- const contractIndex = contracts.findIndex(
207
- (c) => c.contract.target.toString().toLowerCase() === callTarget.toLowerCase()
208
- );
209
- if (contractIndex < 0) {
210
- log("Contract not found, returning false");
211
- return false;
212
- }
213
- const callData = params[0].data;
214
- if (!callData) {
215
- log("Missing call data, returning false");
216
- return false;
217
- }
218
- const methodSignature = callData.slice(2, 10);
219
- if (!methodSignature) {
220
- log("Missing method signature, returning false");
221
- return false;
222
- }
223
- log(`Method signature: ${methodSignature}`);
224
- const { contract, contractMethodsToSign } = contracts[contractIndex];
225
- const isSignable = contractMethodsToSign.some((methodName) => {
226
- const fragment = contract.interface.getFunction(methodName);
227
- return !!fragment && methodSignature.startsWith(fragment.selector.slice(2));
228
- });
229
- log("Is signable contract call:", isSignable);
230
- return isSignable;
231
- }
232
- var defaultGetDelegate = async (provider) => {
233
- return Wallet.createRandom();
234
- };
235
- var prepareTypedDataPayload = (p) => ({
236
- ...p,
237
- params: JSON.stringify(p.params)
238
- });
239
-
240
- // src/Base.ts
241
- var log2 = debug2(DEBUG_NAMESPACE);
242
- var SilentDataRollupBase = class {
243
- constructor(config) {
244
- this.currentDelegateSigner = null;
245
- this.delegateSignerExpires = 0;
246
- this.cachedDelegateHeaders = null;
247
- this.cachedHeadersExpiry = 0;
248
- this.delegateHeadersPromise = null;
249
- this.contracts = [];
250
- this._cachedNetwork = null;
251
- this.config = {
252
- ...config,
253
- authSignatureType: config.authSignatureType ?? "EIP191" /* EIP191 */
254
- };
255
- this.delegateConfig = this.resolveDelegateConfig(config);
256
- log2(
257
- "SilentDataRollupBase initialized with config:",
258
- JSON.stringify(config, null, 2)
259
- );
260
- }
261
- resolveDelegateConfig(config) {
262
- if (config.delegate === true) {
263
- return {
264
- getDelegate: defaultGetDelegate,
265
- expires: DEFAULT_DELEGATE_EXPIRES
266
- };
267
- } else if (typeof config.delegate === "object") {
268
- return {
269
- getDelegate: config.delegate.getDelegate ?? defaultGetDelegate,
270
- expires: config.delegate.expires ?? DEFAULT_DELEGATE_EXPIRES
271
- };
272
- }
273
- return null;
274
- }
275
- /**
276
- * Get cached network with simple caching
277
- * @param provider - The provider to get the network from
278
- * @returns Promise<Network> - The cached or freshly fetched network
279
- */
280
- async getCachedNetwork(provider) {
281
- if (!this._cachedNetwork) {
282
- this._cachedNetwork = await provider.getNetwork();
283
- log2("Network cached:", this._cachedNetwork);
284
- }
285
- return this._cachedNetwork;
286
- }
287
- async getDelegateSigner(provider) {
288
- if (!this.delegateConfig) {
289
- log2("getDelegateSigner: No delegate config, returning null");
290
- return null;
291
- }
292
- const now = Math.floor(Date.now() / 1e3);
293
- log2("getDelegateSigner: Current time:", now);
294
- const isDelegateSignerValid = this.currentDelegateSigner && this.delegateSignerExpires - DELEGATE_EXPIRATION_THRESHOLD_BUFFER > now;
295
- if (isDelegateSignerValid) {
296
- log2(
297
- "getDelegateSigner: Returning existing delegate signer, expires in:",
298
- this.delegateSignerExpires - now,
299
- "seconds"
300
- );
301
- return this.currentDelegateSigner;
302
- } else {
303
- log2("getDelegateSigner: Getting new delegate signer");
304
- try {
305
- const newSigner = await this.delegateConfig.getDelegate(provider);
306
- this.currentDelegateSigner = newSigner;
307
- this.delegateSignerExpires = now + this.delegateConfig.expires;
308
- log2(
309
- "getDelegateSigner: New delegate signer set, expires in:",
310
- this.delegateConfig.expires,
311
- "seconds"
312
- );
313
- return newSigner;
314
- } catch (error) {
315
- log2("getDelegateSigner: Error getting delegate signer:", error);
316
- throw new Error("Failed to get delegate signer");
317
- }
318
- }
319
- }
320
- async getDelegateSignerMessage(provider) {
321
- if (!this.delegateConfig) {
322
- log2("No delegate config, returning null");
323
- return null;
324
- }
325
- const delegateSigner = await this.getDelegateSigner(provider);
326
- if (!delegateSigner) {
327
- log2("Failed to get delegate signer, returning null");
328
- return null;
329
- }
330
- return {
331
- expires: new Date(this.delegateSignerExpires * 1e3).toISOString(),
332
- ephemeralAddress: await delegateSigner.getAddress()
333
- };
334
- }
335
- /**
336
- * Signs a raw delegate header message.
337
- * This method can be overridden by extending classes to customize the signing process.
338
- * The signer implementation decides whether to add EIP-191 prefix or not.
339
- * @param provider - The provider used for signing
340
- * @param message - The delegate signer message to be signed
341
- * @param isSWC - Whether signing for smart wallet contract (EIP-1271)
342
- * @returns A promise that resolves to the signature string
343
- */
344
- async signDelegateHeader(provider, message, isSWC) {
345
- log2("signDelegateHeader: Signing delegate header", message);
346
- let bytesToSign;
347
- if (isSWC) {
348
- const messageHash = keccak2563(toUtf8Bytes3(message));
349
- bytesToSign = getBytes(messageHash);
350
- log2("Signing hash bytes for SWC", messageHash);
351
- } else {
352
- bytesToSign = toUtf8Bytes3(message);
353
- log2("Signing message bytes for EOA", message);
354
- }
355
- const signature = await provider.signer.signMessage(bytesToSign);
356
- log2("signDelegateHeader: Signature generated:", signature);
357
- return signature;
358
- }
359
- /**
360
- * Signs a typed delegate header message.
361
- * This method can be overridden by extending classes to customize the signing process.
362
- * @param provider - The provider used for signing
363
- * @param chainId - The chain ID
364
- * @param message - The delegate signer message to be signed
365
- * @param isSWC - Whether signing for smart wallet contract (EIP-1271)
366
- * @returns A promise that resolves to the signature string
367
- */
368
- async signTypedDelegateHeader(provider, chainId, message, isSWC) {
369
- log2("signTypedDelegateHeader: Signing typed delegate header");
370
- log2(
371
- "signTypedDelegateHeader: Typed message:",
372
- JSON.stringify(message, null, 2)
373
- );
374
- const domain = { ...eip721Domain, chainId };
375
- if (isSWC) {
376
- const messageHash = TypedDataEncoder.hash(
377
- domain,
378
- delegateEIP721Types,
379
- message
380
- );
381
- const hashBytes = getBytes(messageHash);
382
- const signature2 = await provider.signer.signMessage(hashBytes);
383
- log2("signTypedDelegateHeader: Typed SWC signature generated:", signature2);
384
- return signature2;
385
- }
386
- const signature = await provider.signer.signTypedData(
387
- domain,
388
- delegateEIP721Types,
389
- message
390
- );
391
- log2("signTypedDelegateHeader: Signature generated:", signature);
392
- return signature;
393
- }
394
- /**
395
- * IMPORTANT: Return the cached promise (currentPromise), not the resolved value.
396
- * This ensures multiple concurrent callers share the same in-flight request,
397
- * preventing redundant API calls.
398
- */
399
- async getDelegateHeaders(provider) {
400
- log2("Getting delegate headers");
401
- if (!this.delegateHeadersPromise) {
402
- this.delegateHeadersPromise = this.generateDelegateHeaders(provider);
403
- }
404
- const currentPromise = this.delegateHeadersPromise;
405
- try {
406
- const delegateHeaders = await currentPromise;
407
- log2("Delegate headers:", JSON.stringify(delegateHeaders, null, 2));
408
- return currentPromise;
409
- } catch (error) {
410
- log2("Error getting delegate headers:", error);
411
- throw new Error("Failed to get delegate headers");
412
- } finally {
413
- if (this.delegateHeadersPromise === currentPromise) {
414
- this.delegateHeadersPromise = null;
415
- }
416
- }
417
- }
418
- async generateDelegateHeaders(provider) {
419
- const now = Math.floor(Date.now() / 1e3);
420
- const signatureType = this.config.authSignatureType;
421
- const isCachedHeadersValid = this.cachedDelegateHeaders && this.cachedHeadersExpiry - DELEGATE_EXPIRATION_THRESHOLD_BUFFER > now;
422
- if (isCachedHeadersValid) {
423
- log2("Returning cached delegate headers");
424
- return this.cachedDelegateHeaders;
425
- }
426
- try {
427
- const delegateSignerMessage = await this.getDelegateSignerMessage(provider);
428
- if (!delegateSignerMessage) {
429
- throw new Error("Failed to get delegate signer message");
430
- }
431
- const delegateSigner = await this.getDelegateSigner(provider);
432
- if (!delegateSigner) {
433
- throw new Error("Failed to get delegate signer");
434
- }
435
- const headers = {
436
- [HEADER_DELEGATE]: JSON.stringify(delegateSignerMessage)
437
- };
438
- const chainId = (await this.getCachedNetwork(provider)).chainId.toString();
439
- const isSWC = !!this.config.smartWalletAddress;
440
- switch (signatureType) {
441
- case "EIP191" /* EIP191 */:
442
- case "RAW" /* Raw */: {
443
- log2("Generating delegate signature");
444
- const delegateMessageToSign = chainId + JSON.stringify(delegateSignerMessage);
445
- headers[HEADER_DELEGATE_SIGNATURE] = await this.signDelegateHeader(
446
- provider,
447
- delegateMessageToSign,
448
- isSWC
449
- );
450
- break;
451
- }
452
- case "EIP712" /* EIP712 */:
453
- log2("Generating delegate EIP712 signature");
454
- headers[HEADER_EIP712_DELEGATE_SIGNATURE] = await this.signTypedDelegateHeader(
455
- provider,
456
- chainId,
457
- delegateSignerMessage,
458
- isSWC
459
- );
460
- break;
461
- default:
462
- throw new Error(`Unsupported signature type: ${signatureType}`);
463
- }
464
- this.cachedDelegateHeaders = headers;
465
- this.cachedHeadersExpiry = new Date(delegateSignerMessage.expires).getTime() / 1e3;
466
- return this.cachedDelegateHeaders;
467
- } catch (error) {
468
- log2("Error getting delegate headers:", error);
469
- throw new Error("Failed to get delegate headers");
470
- }
471
- }
472
- async getAuthHeaders(provider, payload) {
473
- log2("Getting auth headers", JSON.stringify(payload, null, 2));
474
- const xTimestamp = (/* @__PURE__ */ new Date()).toISOString();
475
- const headers = {
476
- [HEADER_TIMESTAMP]: xTimestamp
477
- };
478
- const chainId = (await this.getCachedNetwork(provider)).chainId.toString();
479
- const signatureType = this.config.authSignatureType ?? "EIP191" /* EIP191 */;
480
- const isSWC = !!this.config.smartWalletAddress;
481
- let payloadToSign = payload;
482
- const isGetUserOperationReceipt = !Array.isArray(payload) && payload.method === "eth_getUserOperationReceipt";
483
- if (isGetUserOperationReceipt) {
484
- log2(
485
- "Detected eth_getUserOperationReceipt, building custom eth_getLogs payload for signing"
486
- );
487
- let fromBlock;
488
- try {
489
- fromBlock = await this.getFromBlockForUserOperationReceipt(provider);
490
- headers[HEADER_FROM_BLOCK] = fromBlock.toString();
491
- log2(`Added ${HEADER_FROM_BLOCK} header:`, fromBlock.toString());
492
- } catch (error) {
493
- log2(
494
- "Error calculating fromBlock for eth_getUserOperationReceipt:",
495
- error
496
- );
497
- throw new Error(
498
- "Failed to calculate fromBlock for eth_getUserOperationReceipt"
499
- );
500
- }
501
- payloadToSign = this.buildGetUserOperationReceiptSigningPayload(
502
- payload,
503
- fromBlock
504
- );
505
- log2(
506
- "Using custom eth_getLogs payload for signing:",
507
- JSON.stringify(payloadToSign, null, 2)
508
- );
509
- }
510
- switch (signatureType) {
511
- case "EIP191" /* EIP191 */:
512
- case "RAW" /* Raw */:
513
- log2("Generating auth header signature");
514
- headers[HEADER_SIGNATURE] = await this.signAuthHeader(
515
- provider,
516
- payloadToSign,
517
- xTimestamp,
518
- chainId,
519
- isSWC
520
- );
521
- break;
522
- case "EIP712" /* EIP712 */:
523
- log2("Generating auth header typed signature");
524
- headers[HEADER_EIP712_SIGNATURE] = await this.signTypedAuthHeader(
525
- provider,
526
- payloadToSign,
527
- xTimestamp,
528
- chainId,
529
- isSWC
530
- );
531
- break;
532
- default:
533
- throw new Error(`Unsupported signature type: ${signatureType}`);
534
- }
535
- log2("Auth headers:", JSON.stringify(headers, null, 2));
536
- return headers;
537
- }
538
- /**
539
- * Signs auth header.
540
- */
541
- async signAuthHeader(provider, payload, timestamp, chainId, isSWC) {
542
- const xMessage = this.prepareMessage(chainId, payload, timestamp);
543
- const delegateSigner = await this.getDelegateSigner(this);
544
- const signer = delegateSigner ?? provider.signer;
545
- const usingDelegate = !!delegateSigner;
546
- let bytesToSign;
547
- if (isSWC && !usingDelegate) {
548
- const messageHash = keccak2563(toUtf8Bytes3(xMessage));
549
- bytesToSign = getBytes(messageHash);
550
- log2("Signing hash bytes for SWC");
551
- } else {
552
- bytesToSign = toUtf8Bytes3(xMessage);
553
- log2("Signing message bytes for EOA");
554
- }
555
- const signature = await signer.signMessage(bytesToSign);
556
- log2("Message signed raw. Signature:", signature);
557
- return signature;
558
- }
559
- /**
560
- * Signs auth header using typed data signature.
561
- */
562
- async signTypedAuthHeader(provider, payload, timestamp, chainId, isSWC) {
563
- const message = this.prepareTypedData(payload, timestamp);
564
- const types = getAuthEIP721Types(payload);
565
- const delegateSigner = await this.getDelegateSigner(this);
566
- const signer = delegateSigner ?? provider.signer;
567
- const usingDelegate = !!delegateSigner;
568
- const domain = { ...eip721Domain, chainId };
569
- if (isSWC && !usingDelegate) {
570
- const messageHash2 = TypedDataEncoder.hash(domain, types, message);
571
- log2("EIP-712 hash (SWC without delegate):", messageHash2);
572
- const hashBytes = getBytes(messageHash2);
573
- const signature2 = await signer.signMessage(hashBytes);
574
- log2("Message signed with EIP-712 for SWC. Signature:", signature2);
575
- return signature2;
576
- }
577
- log2(
578
- "Signing typed data",
579
- JSON.stringify({ message, types, domain }, null, 2)
580
- );
581
- const messageHash = TypedDataEncoder.hash(domain, types, message);
582
- log2("EIP-712 hash (EOA):", messageHash);
583
- const signature = await this.signTypedData(signer, domain, types, message);
584
- log2("Message signed with EIP-712. Signature:", signature);
585
- return signature;
586
- }
587
- /**
588
- * Signs a message using the provided signer.
589
- * This method can be overridden to customize the signing process.
590
- * @param signer - The signer to use
591
- * @param message - The message to sign
592
- * @returns A promise that resolves to the signature string
593
- */
594
- async signMessage(signer, message) {
595
- return signer.signMessage(message);
596
- }
597
- /**
598
- * Signs typed data using the provided signer.
599
- * This method can be overridden to customize the signing process.
600
- * @param signer - The signer to use
601
- * @param domain - The EIP-712 domain
602
- * @param types - The EIP-712 types
603
- * @param message - The message to sign
604
- * @returns A promise that resolves to the signature string
605
- */
606
- async signTypedData(signer, domain, types, message) {
607
- return signer.signTypedData(domain, types, message);
608
- }
609
- setContract(contract, contractMethodsToSign) {
610
- log2("Setting contract and methods to sign: ", contractMethodsToSign);
611
- this.contracts.push({
612
- contract,
613
- contractMethodsToSign
614
- });
615
- }
616
- /**
617
- * Calculates the fromBlock value for eth_getUserOperationReceipt requests.
618
- * Gets the current block number and subtracts the configured userOperationReceiptLookupRange.
619
- *
620
- * IMPORTANT: The bundler strictly validates this value and will reject the request if:
621
- * - The header is missing
622
- * - The value is < 0
623
- * - The value is > current block number
624
- * - The value is too far back (< currentBlock - userOperationReceiptLookupRange)
625
- *
626
- * This method ensures the returned value is always within the valid range:
627
- * max(0, currentBlock - userOperationReceiptLookupRange) <= fromBlock <= currentBlock
628
- *
629
- * @param provider - The provider to use for fetching the current block number
630
- * @returns A promise that resolves to the fromBlock value as a bigint
631
- * @throws Error if unable to fetch the current block number
632
- */
633
- async getFromBlockForUserOperationReceipt(provider) {
634
- const lookupRange = BigInt(
635
- this.config.userOperationReceiptLookupRange ?? DEFAULT_USER_OPERATION_RECEIPT_LOOKUP_RANGE
636
- );
637
- log2("User operation receipt lookup range:", lookupRange.toString());
638
- let currentBlockNumber;
639
- if (typeof provider.getBlockNumber === "function") {
640
- currentBlockNumber = BigInt(await provider.getBlockNumber());
641
- } else if (typeof provider.request === "function") {
642
- const blockNumberHex = await provider.request({
643
- method: "eth_blockNumber",
644
- params: []
645
- });
646
- currentBlockNumber = BigInt(blockNumberHex);
647
- } else {
648
- throw new Error(
649
- "Provider does not support getBlockNumber or request method"
650
- );
651
- }
652
- log2("Current block number:", currentBlockNumber.toString());
653
- const fromBlock = currentBlockNumber > lookupRange ? currentBlockNumber - lookupRange : 0n;
654
- log2("Calculated fromBlock:", fromBlock.toString());
655
- return fromBlock;
656
- }
657
- /**
658
- * Builds a custom eth_getLogs payload for signing when the original request is eth_getUserOperationReceipt.
659
- * This method can be overridden to customize the payload construction.
660
- *
661
- * IMPORTANT: The bundler must reconstruct this exact payload to verify the signature.
662
- * The bundler should use the same `id` from the original eth_getUserOperationReceipt request
663
- * when constructing the eth_getLogs request to send to the RPC node.
664
- *
665
- * @param payload - The original eth_getUserOperationReceipt payload
666
- * @param fromBlock - The fromBlock value to use in the eth_getLogs filter
667
- * @returns A JsonRpcPayload with method 'eth_getLogs' to be used for signing
668
- */
669
- buildGetUserOperationReceiptSigningPayload(payload, fromBlock) {
670
- return {
671
- jsonrpc: payload.jsonrpc,
672
- method: "eth_getLogs",
673
- params: [
674
- {
675
- address: ENTRYPOINT_ADDRESS,
676
- fromBlock: `0x${fromBlock.toString(16)}`,
677
- topics: [
678
- PRIVATE_EVENT_SIGNATURE_HASH,
679
- USER_OPERATION_EVENT_HASH
680
- // eventType
681
- ]
682
- }
683
- ],
684
- id: payload.id ?? 1
685
- };
686
- }
687
- /**
688
- * Prepares the message to be signed for the x-signature header.
689
- */
690
- prepareMessage(chainId, payload, timestamp) {
691
- log2("Preparing raw message for signing", {
692
- payload: JSON.stringify(payload, null, 2),
693
- timestamp
694
- });
695
- const serialRequest = JSON.stringify(payload);
696
- const xMessage = chainId + serialRequest + timestamp;
697
- log2("Raw message to be signed:", xMessage);
698
- return xMessage;
699
- }
700
- /**
701
- * Prepares the message to be signed for the x-eip712-signature header.
702
- */
703
- prepareTypedData(payload, timestamp) {
704
- log2("Preparing payload for signTypedData");
705
- const preparedPayload = Array.isArray(payload) ? payload.map(prepareTypedDataPayload) : prepareTypedDataPayload(payload);
706
- const message = {
707
- request: preparedPayload,
708
- timestamp
709
- };
710
- log2("Prepared payload for signTypedData", JSON.stringify(message, null, 2));
711
- return message;
712
- }
713
- };
714
-
715
- // src/contract.ts
716
- import { Contract as Contract2, Interface } from "ethers";
717
- var SilentDataRollupContract = class extends Contract2 {
718
- constructor(config) {
719
- const { address, abi, runner, contractMethodsToSign } = config;
720
- const contractInterface = new Interface(abi);
721
- contractMethodsToSign.forEach((method) => {
722
- if (!contractInterface.hasFunction(method)) {
723
- throw new Error(
724
- `Method to sign '${method}' not found in the contract ABI`
725
- );
726
- }
727
- });
728
- super(address, abi, runner);
729
- const baseProvider = runner.baseProvider || runner.provider?.baseProvider;
730
- if (typeof baseProvider?.setContract === "function") {
731
- baseProvider.setContract(this, contractMethodsToSign);
732
- }
733
- }
734
- };
735
-
736
- export {
737
- SIGN_RPC_METHODS,
738
- eip721Domain,
739
- delegateEIP721Types,
740
- DEBUG_NAMESPACE,
741
- DEBUG_NAMESPACE_SILENTDATA_INTERCEPTOR,
742
- HEADER_SIGNATURE,
743
- HEADER_TIMESTAMP,
744
- HEADER_SIGNATURE_TYPE,
745
- HEADER_EIP712_SIGNATURE,
746
- HEADER_DELEGATE,
747
- HEADER_DELEGATE_SIGNATURE,
748
- HEADER_EIP712_DELEGATE_SIGNATURE,
749
- HEADER_SIGNER_SWC,
750
- HEADER_FROM_BLOCK,
751
- ENTRYPOINT_ADDRESS,
752
- DEFAULT_USER_OPERATION_RECEIPT_LOOKUP_RANGE,
753
- USER_OPERATION_EVENT_SIGNATURE,
754
- USER_OPERATION_EVENT_HASH,
755
- DEFAULT_DELEGATE_EXPIRES,
756
- DELEGATE_EXPIRATION_THRESHOLD_BUFFER,
757
- WHITELISTED_METHODS,
758
- PRIVATE_EVENT_SIGNATURE,
759
- PRIVATE_EVENT_SIGNATURE_HASH,
760
- calculateEventTypeHash,
761
- ChainId,
762
- NetworkName,
763
- SignatureType,
764
- getAuthEIP721Types,
765
- getAuthHeaders,
766
- isSignableContractCall,
767
- defaultGetDelegate,
768
- prepareTypedDataPayload,
769
- SilentDataRollupBase,
770
- SilentDataRollupContract
771
- };