@appliedblockchain/silentdatarollup-core 1.0.7 → 1.0.9
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.
- package/LICENSE +21 -0
- package/README.md +1 -1
- package/dist/{chunk-5VQIOQAW.mjs → chunk-53A5RGL2.mjs} +242 -95
- package/dist/index.d.mts +96 -9
- package/dist/index.d.ts +96 -9
- package/dist/index.js +243 -90
- package/dist/index.mjs +15 -1
- package/dist/tests.js +15 -9
- package/dist/tests.mjs +1 -1
- package/package.json +8 -9
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Applied Blockchain Ltd.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
// src/Base.ts
|
|
2
2
|
import debug2 from "debug";
|
|
3
|
+
import {
|
|
4
|
+
getBytes,
|
|
5
|
+
keccak256 as keccak2563,
|
|
6
|
+
toUtf8Bytes as toUtf8Bytes3,
|
|
7
|
+
TypedDataEncoder
|
|
8
|
+
} from "ethers";
|
|
3
9
|
|
|
4
10
|
// src/constants.ts
|
|
11
|
+
import { keccak256, toUtf8Bytes } from "ethers";
|
|
5
12
|
var SIGN_RPC_METHODS = [
|
|
6
13
|
"eth_estimateGas",
|
|
7
14
|
"eth_getProof",
|
|
8
15
|
"eth_getTransactionByHash",
|
|
9
|
-
"eth_getTransactionReceipt"
|
|
16
|
+
"eth_getTransactionReceipt",
|
|
17
|
+
"eth_getUserOperationReceipt",
|
|
18
|
+
"eth_getUserOperationByHash"
|
|
10
19
|
];
|
|
11
20
|
var eip721Domain = {
|
|
12
21
|
name: "Silent Data [Rollup]",
|
|
@@ -22,10 +31,19 @@ var DEBUG_NAMESPACE = "silentdata:core";
|
|
|
22
31
|
var DEBUG_NAMESPACE_SILENTDATA_INTERCEPTOR = "silentdata:interceptor";
|
|
23
32
|
var HEADER_SIGNATURE = "x-signature";
|
|
24
33
|
var HEADER_TIMESTAMP = "x-timestamp";
|
|
34
|
+
var HEADER_SIGNATURE_TYPE = "x-signature-type";
|
|
25
35
|
var HEADER_EIP712_SIGNATURE = "x-eip712-signature";
|
|
26
36
|
var HEADER_DELEGATE = "x-delegate";
|
|
27
37
|
var HEADER_DELEGATE_SIGNATURE = "x-delegate-signature";
|
|
28
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
|
+
);
|
|
29
47
|
var DEFAULT_DELEGATE_EXPIRES = 10 * 60 * 60;
|
|
30
48
|
var DELEGATE_EXPIRATION_THRESHOLD_BUFFER = 5;
|
|
31
49
|
var WHITELISTED_METHODS = [
|
|
@@ -41,19 +59,15 @@ var WHITELISTED_METHODS = [
|
|
|
41
59
|
"eth_getCode",
|
|
42
60
|
"eth_getFilterChanges",
|
|
43
61
|
"eth_getFilterLogs",
|
|
44
|
-
"eth_getHashrate",
|
|
45
62
|
"eth_getHeaderByHash",
|
|
46
63
|
"eth_getLogs",
|
|
47
64
|
"eth_getProof",
|
|
48
65
|
"eth_getTransactionByHash",
|
|
49
66
|
"eth_getTransactionCount",
|
|
50
67
|
"eth_getTransactionReceipt",
|
|
51
|
-
"eth_hashrate",
|
|
52
68
|
"eth_maxPriorityFeePerGas",
|
|
53
|
-
"eth_mining",
|
|
54
69
|
"eth_newBlockFilter",
|
|
55
70
|
"eth_sendRawTransaction",
|
|
56
|
-
"eth_submitTransaction",
|
|
57
71
|
"eth_syncing",
|
|
58
72
|
"eth_newFilter",
|
|
59
73
|
"eth_newPendingTransactionFilter",
|
|
@@ -61,21 +75,19 @@ var WHITELISTED_METHODS = [
|
|
|
61
75
|
"net_version",
|
|
62
76
|
"net_peerCount",
|
|
63
77
|
"web3_clientVersion",
|
|
64
|
-
"web3_sha3"
|
|
65
|
-
"zkevm_batchNumber",
|
|
66
|
-
"zkevm_batchNumberByBlockNumber",
|
|
67
|
-
"zkevm_consolidatedBlockNumber",
|
|
68
|
-
"zkevm_estimateGasPrice",
|
|
69
|
-
"zkevm_getBatchByNumber",
|
|
70
|
-
"zkevm_getFullBlockByHash",
|
|
71
|
-
"zkevm_getFullBlockByNumber",
|
|
72
|
-
"zkevm_getLatestGlobalExitRoot",
|
|
73
|
-
"zkevm_isBlockConsolidated",
|
|
74
|
-
"zkevm_isBlockVirtualized",
|
|
75
|
-
"zkevm_verifiedBatchNumber",
|
|
76
|
-
"zkevm_virtualBatchNumber"
|
|
78
|
+
"web3_sha3"
|
|
77
79
|
];
|
|
78
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
|
+
|
|
79
91
|
// src/types.ts
|
|
80
92
|
var ChainId = /* @__PURE__ */ ((ChainId2) => {
|
|
81
93
|
ChainId2[ChainId2["MAINNET"] = 380929] = "MAINNET";
|
|
@@ -238,7 +250,7 @@ var SilentDataRollupBase = class {
|
|
|
238
250
|
this._cachedNetwork = null;
|
|
239
251
|
this.config = {
|
|
240
252
|
...config,
|
|
241
|
-
authSignatureType: config.authSignatureType ?? "
|
|
253
|
+
authSignatureType: config.authSignatureType ?? "EIP191" /* EIP191 */
|
|
242
254
|
};
|
|
243
255
|
this.delegateConfig = this.resolveDelegateConfig(config);
|
|
244
256
|
log2(
|
|
@@ -323,37 +335,67 @@ var SilentDataRollupBase = class {
|
|
|
323
335
|
/**
|
|
324
336
|
* Signs a raw delegate header message.
|
|
325
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.
|
|
326
339
|
* @param provider - The provider used for signing
|
|
327
340
|
* @param message - The delegate signer message to be signed
|
|
341
|
+
* @param isSWC - Whether signing for smart wallet contract (EIP-1271)
|
|
328
342
|
* @returns A promise that resolves to the signature string
|
|
329
343
|
*/
|
|
330
|
-
async
|
|
331
|
-
log2("
|
|
332
|
-
|
|
333
|
-
|
|
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);
|
|
334
357
|
return signature;
|
|
335
358
|
}
|
|
336
359
|
/**
|
|
337
360
|
* Signs a typed delegate header message.
|
|
338
361
|
* This method can be overridden by extending classes to customize the signing process.
|
|
339
362
|
* @param provider - The provider used for signing
|
|
363
|
+
* @param chainId - The chain ID
|
|
340
364
|
* @param message - The delegate signer message to be signed
|
|
365
|
+
* @param isSWC - Whether signing for smart wallet contract (EIP-1271)
|
|
341
366
|
* @returns A promise that resolves to the signature string
|
|
342
367
|
*/
|
|
343
|
-
async signTypedDelegateHeader(provider, chainId, message) {
|
|
368
|
+
async signTypedDelegateHeader(provider, chainId, message, isSWC) {
|
|
344
369
|
log2("signTypedDelegateHeader: Signing typed delegate header");
|
|
345
370
|
log2(
|
|
346
371
|
"signTypedDelegateHeader: Typed message:",
|
|
347
372
|
JSON.stringify(message, null, 2)
|
|
348
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
|
+
}
|
|
349
386
|
const signature = await provider.signer.signTypedData(
|
|
350
|
-
|
|
387
|
+
domain,
|
|
351
388
|
delegateEIP721Types,
|
|
352
389
|
message
|
|
353
390
|
);
|
|
354
391
|
log2("signTypedDelegateHeader: Signature generated:", signature);
|
|
355
392
|
return signature;
|
|
356
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
|
+
*/
|
|
357
399
|
async getDelegateHeaders(provider) {
|
|
358
400
|
log2("Getting delegate headers");
|
|
359
401
|
if (!this.delegateHeadersPromise) {
|
|
@@ -361,7 +403,9 @@ var SilentDataRollupBase = class {
|
|
|
361
403
|
}
|
|
362
404
|
const currentPromise = this.delegateHeadersPromise;
|
|
363
405
|
try {
|
|
364
|
-
|
|
406
|
+
const delegateHeaders = await currentPromise;
|
|
407
|
+
log2("Delegate headers:", JSON.stringify(delegateHeaders, null, 2));
|
|
408
|
+
return currentPromise;
|
|
365
409
|
} catch (error) {
|
|
366
410
|
log2("Error getting delegate headers:", error);
|
|
367
411
|
throw new Error("Failed to get delegate headers");
|
|
@@ -392,13 +436,16 @@ var SilentDataRollupBase = class {
|
|
|
392
436
|
[HEADER_DELEGATE]: JSON.stringify(delegateSignerMessage)
|
|
393
437
|
};
|
|
394
438
|
const chainId = (await this.getCachedNetwork(provider)).chainId.toString();
|
|
439
|
+
const isSWC = !!this.config.smartWalletAddress;
|
|
395
440
|
switch (signatureType) {
|
|
441
|
+
case "EIP191" /* EIP191 */:
|
|
396
442
|
case "RAW" /* Raw */: {
|
|
397
|
-
log2("Generating delegate
|
|
443
|
+
log2("Generating delegate signature");
|
|
398
444
|
const delegateMessageToSign = chainId + JSON.stringify(delegateSignerMessage);
|
|
399
|
-
headers[HEADER_DELEGATE_SIGNATURE] = await this.
|
|
445
|
+
headers[HEADER_DELEGATE_SIGNATURE] = await this.signDelegateHeader(
|
|
400
446
|
provider,
|
|
401
|
-
delegateMessageToSign
|
|
447
|
+
delegateMessageToSign,
|
|
448
|
+
isSWC
|
|
402
449
|
);
|
|
403
450
|
break;
|
|
404
451
|
}
|
|
@@ -407,7 +454,8 @@ var SilentDataRollupBase = class {
|
|
|
407
454
|
headers[HEADER_EIP712_DELEGATE_SIGNATURE] = await this.signTypedDelegateHeader(
|
|
408
455
|
provider,
|
|
409
456
|
chainId,
|
|
410
|
-
delegateSignerMessage
|
|
457
|
+
delegateSignerMessage,
|
|
458
|
+
isSWC
|
|
411
459
|
);
|
|
412
460
|
break;
|
|
413
461
|
default:
|
|
@@ -428,24 +476,57 @@ var SilentDataRollupBase = class {
|
|
|
428
476
|
[HEADER_TIMESTAMP]: xTimestamp
|
|
429
477
|
};
|
|
430
478
|
const chainId = (await this.getCachedNetwork(provider)).chainId.toString();
|
|
431
|
-
const signatureType = this.config.authSignatureType
|
|
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
|
+
}
|
|
432
510
|
switch (signatureType) {
|
|
511
|
+
case "EIP191" /* EIP191 */:
|
|
433
512
|
case "RAW" /* Raw */:
|
|
434
|
-
log2("Generating auth header
|
|
435
|
-
headers[HEADER_SIGNATURE] = await this.
|
|
513
|
+
log2("Generating auth header signature");
|
|
514
|
+
headers[HEADER_SIGNATURE] = await this.signAuthHeader(
|
|
436
515
|
provider,
|
|
437
|
-
|
|
516
|
+
payloadToSign,
|
|
438
517
|
xTimestamp,
|
|
439
|
-
chainId
|
|
518
|
+
chainId,
|
|
519
|
+
isSWC
|
|
440
520
|
);
|
|
441
521
|
break;
|
|
442
522
|
case "EIP712" /* EIP712 */:
|
|
443
|
-
log2("Generating auth
|
|
444
|
-
headers[HEADER_EIP712_SIGNATURE] = await this.
|
|
523
|
+
log2("Generating auth header typed signature");
|
|
524
|
+
headers[HEADER_EIP712_SIGNATURE] = await this.signTypedAuthHeader(
|
|
445
525
|
provider,
|
|
446
|
-
|
|
526
|
+
payloadToSign,
|
|
447
527
|
xTimestamp,
|
|
448
|
-
chainId
|
|
528
|
+
chainId,
|
|
529
|
+
isSWC
|
|
449
530
|
);
|
|
450
531
|
break;
|
|
451
532
|
default:
|
|
@@ -454,26 +535,53 @@ var SilentDataRollupBase = class {
|
|
|
454
535
|
log2("Auth headers:", JSON.stringify(headers, null, 2));
|
|
455
536
|
return headers;
|
|
456
537
|
}
|
|
457
|
-
|
|
458
|
-
|
|
538
|
+
/**
|
|
539
|
+
* Signs auth header.
|
|
540
|
+
*/
|
|
541
|
+
async signAuthHeader(provider, payload, timestamp, chainId, isSWC) {
|
|
542
|
+
const xMessage = this.prepareMessage(chainId, payload, timestamp);
|
|
459
543
|
const delegateSigner = await this.getDelegateSigner(this);
|
|
460
544
|
const signer = delegateSigner ?? provider.signer;
|
|
461
|
-
const
|
|
462
|
-
|
|
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);
|
|
463
557
|
return signature;
|
|
464
558
|
}
|
|
465
|
-
|
|
466
|
-
|
|
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);
|
|
467
564
|
const types = getAuthEIP721Types(payload);
|
|
468
565
|
const delegateSigner = await this.getDelegateSigner(this);
|
|
469
566
|
const signer = delegateSigner ?? provider.signer;
|
|
567
|
+
const usingDelegate = !!delegateSigner;
|
|
470
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
|
+
}
|
|
471
577
|
log2(
|
|
472
578
|
"Signing typed data",
|
|
473
579
|
JSON.stringify({ message, types, domain }, null, 2)
|
|
474
580
|
);
|
|
581
|
+
const messageHash = TypedDataEncoder.hash(domain, types, message);
|
|
582
|
+
log2("EIP-712 hash (EOA):", messageHash);
|
|
475
583
|
const signature = await this.signTypedData(signer, domain, types, message);
|
|
476
|
-
log2("Message signed. Signature:", signature);
|
|
584
|
+
log2("Message signed with EIP-712. Signature:", signature);
|
|
477
585
|
return signature;
|
|
478
586
|
}
|
|
479
587
|
/**
|
|
@@ -505,10 +613,81 @@ var SilentDataRollupBase = class {
|
|
|
505
613
|
contractMethodsToSign
|
|
506
614
|
});
|
|
507
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
|
+
}
|
|
508
687
|
/**
|
|
509
688
|
* Prepares the message to be signed for the x-signature header.
|
|
510
689
|
*/
|
|
511
|
-
|
|
690
|
+
prepareMessage(chainId, payload, timestamp) {
|
|
512
691
|
log2("Preparing raw message for signing", {
|
|
513
692
|
payload: JSON.stringify(payload, null, 2),
|
|
514
693
|
timestamp
|
|
@@ -521,7 +700,7 @@ var SilentDataRollupBase = class {
|
|
|
521
700
|
/**
|
|
522
701
|
* Prepares the message to be signed for the x-eip712-signature header.
|
|
523
702
|
*/
|
|
524
|
-
|
|
703
|
+
prepareTypedData(payload, timestamp) {
|
|
525
704
|
log2("Preparing payload for signTypedData");
|
|
526
705
|
const preparedPayload = Array.isArray(payload) ? payload.map(prepareTypedDataPayload) : prepareTypedDataPayload(payload);
|
|
527
706
|
const message = {
|
|
@@ -534,38 +713,10 @@ var SilentDataRollupBase = class {
|
|
|
534
713
|
};
|
|
535
714
|
|
|
536
715
|
// src/contract.ts
|
|
537
|
-
import {
|
|
538
|
-
|
|
539
|
-
Interface,
|
|
540
|
-
assertArgument
|
|
541
|
-
} from "ethers";
|
|
542
|
-
var CustomContractRunner = class {
|
|
543
|
-
constructor(provider, signer) {
|
|
544
|
-
this.provider = provider;
|
|
545
|
-
this.signer = signer;
|
|
546
|
-
}
|
|
547
|
-
async sendTransaction(tx) {
|
|
548
|
-
if (!tx.gasLimit) {
|
|
549
|
-
tx.gasLimit = await this.provider.estimateGas(tx);
|
|
550
|
-
}
|
|
551
|
-
return this.signer.sendTransaction(tx);
|
|
552
|
-
}
|
|
553
|
-
};
|
|
554
|
-
function getContractRunner(runner, provider) {
|
|
555
|
-
const runnerIsSigner = typeof runner.sendTransaction === "function";
|
|
556
|
-
if (!runnerIsSigner) {
|
|
557
|
-
return runner;
|
|
558
|
-
}
|
|
559
|
-
const runnerProviderConstructor = runner.provider?.constructor.name ?? "";
|
|
560
|
-
if (!runnerProviderConstructor.includes("SilentDataRollupProvider")) {
|
|
561
|
-
assertArgument(provider, "provider is mandatory", "provider", provider);
|
|
562
|
-
return new CustomContractRunner(provider, runner);
|
|
563
|
-
}
|
|
564
|
-
return new CustomContractRunner(runner.provider, runner);
|
|
565
|
-
}
|
|
566
|
-
var SilentDataRollupContract = class extends Contract {
|
|
716
|
+
import { Contract as Contract2, Interface } from "ethers";
|
|
717
|
+
var SilentDataRollupContract = class extends Contract2 {
|
|
567
718
|
constructor(config) {
|
|
568
|
-
const { address, abi, runner, contractMethodsToSign
|
|
719
|
+
const { address, abi, runner, contractMethodsToSign } = config;
|
|
569
720
|
const contractInterface = new Interface(abi);
|
|
570
721
|
contractMethodsToSign.forEach((method) => {
|
|
571
722
|
if (!contractInterface.hasFunction(method)) {
|
|
@@ -574,8 +725,7 @@ var SilentDataRollupContract = class extends Contract {
|
|
|
574
725
|
);
|
|
575
726
|
}
|
|
576
727
|
});
|
|
577
|
-
|
|
578
|
-
super(address, abi, contractRunner);
|
|
728
|
+
super(address, abi, runner);
|
|
579
729
|
const baseProvider = runner.baseProvider || runner.provider?.baseProvider;
|
|
580
730
|
if (typeof baseProvider?.setContract === "function") {
|
|
581
731
|
baseProvider.setContract(this, contractMethodsToSign);
|
|
@@ -583,16 +733,6 @@ var SilentDataRollupContract = class extends Contract {
|
|
|
583
733
|
}
|
|
584
734
|
};
|
|
585
735
|
|
|
586
|
-
// src/privateEvents.ts
|
|
587
|
-
import { keccak256, toUtf8Bytes } from "ethers";
|
|
588
|
-
var PRIVATE_EVENT_SIGNATURE = "PrivateEvent(address[],bytes32,bytes)";
|
|
589
|
-
var PRIVATE_EVENT_SIGNATURE_HASH = keccak256(
|
|
590
|
-
toUtf8Bytes(PRIVATE_EVENT_SIGNATURE)
|
|
591
|
-
);
|
|
592
|
-
function calculateEventTypeHash(eventSignature) {
|
|
593
|
-
return keccak256(toUtf8Bytes(eventSignature));
|
|
594
|
-
}
|
|
595
|
-
|
|
596
736
|
export {
|
|
597
737
|
SIGN_RPC_METHODS,
|
|
598
738
|
eip721Domain,
|
|
@@ -601,13 +741,23 @@ export {
|
|
|
601
741
|
DEBUG_NAMESPACE_SILENTDATA_INTERCEPTOR,
|
|
602
742
|
HEADER_SIGNATURE,
|
|
603
743
|
HEADER_TIMESTAMP,
|
|
744
|
+
HEADER_SIGNATURE_TYPE,
|
|
604
745
|
HEADER_EIP712_SIGNATURE,
|
|
605
746
|
HEADER_DELEGATE,
|
|
606
747
|
HEADER_DELEGATE_SIGNATURE,
|
|
607
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,
|
|
608
755
|
DEFAULT_DELEGATE_EXPIRES,
|
|
609
756
|
DELEGATE_EXPIRATION_THRESHOLD_BUFFER,
|
|
610
757
|
WHITELISTED_METHODS,
|
|
758
|
+
PRIVATE_EVENT_SIGNATURE,
|
|
759
|
+
PRIVATE_EVENT_SIGNATURE_HASH,
|
|
760
|
+
calculateEventTypeHash,
|
|
611
761
|
ChainId,
|
|
612
762
|
NetworkName,
|
|
613
763
|
SignatureType,
|
|
@@ -617,8 +767,5 @@ export {
|
|
|
617
767
|
defaultGetDelegate,
|
|
618
768
|
prepareTypedDataPayload,
|
|
619
769
|
SilentDataRollupBase,
|
|
620
|
-
SilentDataRollupContract
|
|
621
|
-
PRIVATE_EVENT_SIGNATURE,
|
|
622
|
-
PRIVATE_EVENT_SIGNATURE_HASH,
|
|
623
|
-
calculateEventTypeHash
|
|
770
|
+
SilentDataRollupContract
|
|
624
771
|
};
|