@appliedblockchain/silentdatarollup-ethers-provider 1.0.1 → 1.0.3
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/README.md +110 -0
- package/dist/index.d.mts +81 -2
- package/dist/index.d.ts +81 -2
- package/dist/index.js +193 -2
- package/dist/index.mjs +184 -2
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
- [Usage with a Contract](#usage-with-a-contract)
|
|
12
12
|
- [Installing Usage with a Contract Dependencies](#installing-usage-with-a-contract-dependencies)
|
|
13
13
|
- [Usage with a Contract Example](#usage-with-a-contract-example)
|
|
14
|
+
- [Private Events](#private-events)
|
|
15
|
+
- [Overview](#overview)
|
|
16
|
+
- [Using the SDInterface](#using-the-sdinterface)
|
|
17
|
+
- [Private Events Example](#private-events-example)
|
|
14
18
|
- [Troubleshooting](#troubleshooting)
|
|
15
19
|
- [License](#license)
|
|
16
20
|
- [Additional Resources](#additional-resources)
|
|
@@ -106,6 +110,112 @@ const publicMethodResult = await contract.method3('param1', 'param2')
|
|
|
106
110
|
console.log('Public method result:', publicMethodResult)
|
|
107
111
|
```
|
|
108
112
|
|
|
113
|
+
### Private Events
|
|
114
|
+
|
|
115
|
+
#### Overview
|
|
116
|
+
|
|
117
|
+
Silent Data Rollup supports Private Events, which are blockchain events that are only visible to authorized users. The `SilentDataRollupProvider` includes specialized methods for working with these private events:
|
|
118
|
+
|
|
119
|
+
- `getAllLogs()` - Returns both regular and private events
|
|
120
|
+
- `getPrivateLogs()` - Returns only private events
|
|
121
|
+
|
|
122
|
+
Private events are wrapped in a `PrivateEvent` event with the following structure:
|
|
123
|
+
|
|
124
|
+
```solidity
|
|
125
|
+
event PrivateEvent(
|
|
126
|
+
address[] allowedViewers,
|
|
127
|
+
bytes32 indexed eventType,
|
|
128
|
+
bytes payload
|
|
129
|
+
);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Using the SDInterface
|
|
133
|
+
|
|
134
|
+
To easily decode private events, use the `SDInterface` class which extends ethers' `Interface`:
|
|
135
|
+
|
|
136
|
+
1. Create an `SDInterface` instance with your contract ABI plus **the private additional event signatures**
|
|
137
|
+
2. Use it to parse logs from `getAllLogs()` or `getPrivateLogs()`
|
|
138
|
+
3. Access the decoded inner event via the `innerLog` property of the parsed log
|
|
139
|
+
|
|
140
|
+
#### Private Events Example
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import {
|
|
144
|
+
SDInterface,
|
|
145
|
+
SilentDataRollupProvider,
|
|
146
|
+
} from '@appliedblockchain/silentdatarollup-ethers-provider'
|
|
147
|
+
|
|
148
|
+
// Initialize provider
|
|
149
|
+
const provider = new SilentDataRollupProvider({
|
|
150
|
+
rpcUrl: 'SILENT_DATA_ROLLUP_RPC_URL',
|
|
151
|
+
network: NetworkName.TESTNET,
|
|
152
|
+
privateKey: 'YOUR_PRIVATE_KEY',
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// Contract ABI with PrivateEvent definition
|
|
156
|
+
const contractAbi = [
|
|
157
|
+
{
|
|
158
|
+
anonymous: false,
|
|
159
|
+
inputs: [
|
|
160
|
+
{
|
|
161
|
+
indexed: false,
|
|
162
|
+
internalType: 'address[]',
|
|
163
|
+
name: 'allowedViewers',
|
|
164
|
+
type: 'address[]',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
indexed: true,
|
|
168
|
+
internalType: 'bytes32',
|
|
169
|
+
name: 'eventType',
|
|
170
|
+
type: 'bytes32',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
indexed: false,
|
|
174
|
+
internalType: 'bytes',
|
|
175
|
+
name: 'payload',
|
|
176
|
+
type: 'bytes',
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
name: 'PrivateEvent',
|
|
180
|
+
type: 'event',
|
|
181
|
+
},
|
|
182
|
+
// Your other contract events and functions...
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
// Create SDInterface with contract ABI and any additional event signatures
|
|
186
|
+
const sdInterface = new SDInterface([
|
|
187
|
+
...contractAbi,
|
|
188
|
+
// Note: The private event doesn't have indexed params.
|
|
189
|
+
// Add any other event signatures that might be emitted privately
|
|
190
|
+
'event TransferPrivate(address from, address to, uint256 value)',
|
|
191
|
+
])
|
|
192
|
+
|
|
193
|
+
// Get private events
|
|
194
|
+
const privateEvents = await provider.getPrivateLogs({
|
|
195
|
+
address: 'YOUR_CONTRACT_ADDRESS',
|
|
196
|
+
// Optional: Filter by specific event type
|
|
197
|
+
eventSignature: 'TransferPrivate(address,address,uint256)',
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
// Parse and access private events
|
|
201
|
+
for (const log of privateEvents) {
|
|
202
|
+
const parsedLog = sdInterface.parseLog(log)
|
|
203
|
+
|
|
204
|
+
console.log('Private Event:', parsedLog.name) // Will be 'PrivateEvent'
|
|
205
|
+
console.log('Private Args:', parsedLog.args) // Raw PrivateEvent args
|
|
206
|
+
|
|
207
|
+
// Access the decoded inner event
|
|
208
|
+
if (parsedLog.innerLog) {
|
|
209
|
+
console.log('Decoded Private Event:', parsedLog.innerLog.name) // e.g., 'TransferPrivate'
|
|
210
|
+
console.log('Decoded Private Args:', parsedLog.innerLog.args) // Decoded inner event args
|
|
211
|
+
|
|
212
|
+
// Access args by name
|
|
213
|
+
const { from, to, value } = parsedLog.innerLog.args
|
|
214
|
+
console.log(`Transfer from ${from} to ${to}: ${value}`)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
109
219
|
## License
|
|
110
220
|
|
|
111
221
|
This project is licensed under the [MIT License](LICENSE).
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Signer, JsonRpcApiProviderOptions, JsonRpcProvider, JsonRpcPayload, JsonRpcResult, FetchRequest } from 'ethers';
|
|
1
|
+
import { Signer, JsonRpcApiProviderOptions, Filter, JsonRpcProvider, JsonRpcPayload, JsonRpcResult, FetchRequest, Log, FilterByBlockHash, LogDescription, Interface } from 'ethers';
|
|
2
2
|
import { BaseConfig, NetworkName } from '@appliedblockchain/silentdatarollup-core';
|
|
3
3
|
|
|
4
4
|
declare const SIGN_RPC_METHODS: string[];
|
|
5
|
+
declare const DEBUG_NAMESPACE = "silentdata:ethers-provider";
|
|
5
6
|
|
|
6
7
|
interface SilentDataRollupProviderConfig extends BaseConfig {
|
|
7
8
|
rpcUrl: string;
|
|
@@ -11,6 +12,24 @@ interface SilentDataRollupProviderConfig extends BaseConfig {
|
|
|
11
12
|
signer?: Signer;
|
|
12
13
|
options?: JsonRpcApiProviderOptions;
|
|
13
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Extended filter type that includes a special flag for private events
|
|
17
|
+
* This flag is used to identify when a call to eth_getLogs originated from
|
|
18
|
+
* the getAllLogs method, so we can add authentication headers
|
|
19
|
+
*/
|
|
20
|
+
interface PrivateEventsFilter extends Filter {
|
|
21
|
+
/**
|
|
22
|
+
* Internal flag to identify requests that should include auth headers
|
|
23
|
+
* Set automatically by getAllLogs method
|
|
24
|
+
*/
|
|
25
|
+
_isPrivateEvent?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Optional event signature for filtering private events by type
|
|
28
|
+
* Example: "Transfer(address,address,uint256)"
|
|
29
|
+
* Will be converted to a hash and used for topic filtering
|
|
30
|
+
*/
|
|
31
|
+
eventSignature?: string;
|
|
32
|
+
}
|
|
14
33
|
|
|
15
34
|
declare class SilentDataRollupProvider extends JsonRpcProvider {
|
|
16
35
|
private config;
|
|
@@ -22,6 +41,66 @@ declare class SilentDataRollupProvider extends JsonRpcProvider {
|
|
|
22
41
|
rpcUrl: string;
|
|
23
42
|
}): FetchRequest;
|
|
24
43
|
clone(): SilentDataRollupProvider;
|
|
44
|
+
/**
|
|
45
|
+
* Helper method to configure a filter for private events
|
|
46
|
+
* @param filter - The original filter
|
|
47
|
+
* @param forcePrivateOnly - Whether to force filtering for only PrivateEvents
|
|
48
|
+
* @returns The configured filter with proper topics
|
|
49
|
+
*/
|
|
50
|
+
private configurePrivateEventsFilter;
|
|
51
|
+
/**
|
|
52
|
+
* Gets logs for private events, including authentication headers
|
|
53
|
+
* @param filter - The filter parameters for logs
|
|
54
|
+
* @returns Array of logs matching the filter
|
|
55
|
+
*/
|
|
56
|
+
getAllLogs(filter?: PrivateEventsFilter): Promise<Array<Log>>;
|
|
57
|
+
/**
|
|
58
|
+
* Gets only private events (PrivateEvent logs), including authentication headers
|
|
59
|
+
* @param filter - The filter parameters for logs
|
|
60
|
+
* @returns Array of logs matching the filter, containing only PrivateEvent logs
|
|
61
|
+
*/
|
|
62
|
+
getPrivateLogs(filter?: PrivateEventsFilter): Promise<Log[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Override of ethers' getLogs method that preserves our custom _isPrivateEvent property
|
|
65
|
+
*
|
|
66
|
+
* IMPORTANT: This method mimics the behavior of ethers' original getLogs implementation
|
|
67
|
+
* but adds a crucial step to preserve the _isPrivateEvent flag. We need this because:
|
|
68
|
+
*
|
|
69
|
+
* 1. Ethers' _getFilter method sanitizes filter objects, removing any non-standard properties
|
|
70
|
+
* 2. Our _isPrivateEvent flag would be stripped by this sanitization
|
|
71
|
+
* 3. We need the flag to reach the _send method to trigger the addition of auth headers
|
|
72
|
+
*
|
|
73
|
+
* The approach here is to run the normal filter processing, then re-attach our flag as a
|
|
74
|
+
* non-enumerable property to avoid JSON serialization issues. This allows the flag to
|
|
75
|
+
* survive until _send where we check for it to determine if auth headers are needed.
|
|
76
|
+
*
|
|
77
|
+
* @param _filter - The filter with our potential _isPrivateEvent property
|
|
78
|
+
* @returns Array of logs matching the filter
|
|
79
|
+
*/
|
|
80
|
+
getLogs(_filter: PrivateEventsFilter | FilterByBlockHash): Promise<Log[]>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Extended LogDescription type that includes private event details
|
|
85
|
+
*/
|
|
86
|
+
interface SDLogDescription extends LogDescription {
|
|
87
|
+
/**
|
|
88
|
+
* Only present for PrivateEvents - contains the decoded inner log
|
|
89
|
+
* If decoding failed, this will be null
|
|
90
|
+
*/
|
|
91
|
+
innerLog?: LogDescription | null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Extends ethers Interface to provide support for decoding PrivateEvent logs
|
|
95
|
+
* Make sure to include the PrivateEvent signature in your ABI when using this class
|
|
96
|
+
*/
|
|
97
|
+
declare class SDInterface extends Interface {
|
|
98
|
+
/**
|
|
99
|
+
* Extends the parseLog method to handle PrivateEvent logs
|
|
100
|
+
* @param log - The log to parse
|
|
101
|
+
* @returns The parsed log description with additional private event details if applicable
|
|
102
|
+
*/
|
|
103
|
+
parseLog(log: Parameters<Interface['parseLog']>[0]): SDLogDescription | null;
|
|
25
104
|
}
|
|
26
105
|
|
|
27
|
-
export { SIGN_RPC_METHODS, SilentDataRollupProvider, type SilentDataRollupProviderConfig };
|
|
106
|
+
export { DEBUG_NAMESPACE, type PrivateEventsFilter, SDInterface, type SDLogDescription, SIGN_RPC_METHODS, SilentDataRollupProvider, type SilentDataRollupProviderConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Signer, JsonRpcApiProviderOptions, JsonRpcProvider, JsonRpcPayload, JsonRpcResult, FetchRequest } from 'ethers';
|
|
1
|
+
import { Signer, JsonRpcApiProviderOptions, Filter, JsonRpcProvider, JsonRpcPayload, JsonRpcResult, FetchRequest, Log, FilterByBlockHash, LogDescription, Interface } from 'ethers';
|
|
2
2
|
import { BaseConfig, NetworkName } from '@appliedblockchain/silentdatarollup-core';
|
|
3
3
|
|
|
4
4
|
declare const SIGN_RPC_METHODS: string[];
|
|
5
|
+
declare const DEBUG_NAMESPACE = "silentdata:ethers-provider";
|
|
5
6
|
|
|
6
7
|
interface SilentDataRollupProviderConfig extends BaseConfig {
|
|
7
8
|
rpcUrl: string;
|
|
@@ -11,6 +12,24 @@ interface SilentDataRollupProviderConfig extends BaseConfig {
|
|
|
11
12
|
signer?: Signer;
|
|
12
13
|
options?: JsonRpcApiProviderOptions;
|
|
13
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Extended filter type that includes a special flag for private events
|
|
17
|
+
* This flag is used to identify when a call to eth_getLogs originated from
|
|
18
|
+
* the getAllLogs method, so we can add authentication headers
|
|
19
|
+
*/
|
|
20
|
+
interface PrivateEventsFilter extends Filter {
|
|
21
|
+
/**
|
|
22
|
+
* Internal flag to identify requests that should include auth headers
|
|
23
|
+
* Set automatically by getAllLogs method
|
|
24
|
+
*/
|
|
25
|
+
_isPrivateEvent?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Optional event signature for filtering private events by type
|
|
28
|
+
* Example: "Transfer(address,address,uint256)"
|
|
29
|
+
* Will be converted to a hash and used for topic filtering
|
|
30
|
+
*/
|
|
31
|
+
eventSignature?: string;
|
|
32
|
+
}
|
|
14
33
|
|
|
15
34
|
declare class SilentDataRollupProvider extends JsonRpcProvider {
|
|
16
35
|
private config;
|
|
@@ -22,6 +41,66 @@ declare class SilentDataRollupProvider extends JsonRpcProvider {
|
|
|
22
41
|
rpcUrl: string;
|
|
23
42
|
}): FetchRequest;
|
|
24
43
|
clone(): SilentDataRollupProvider;
|
|
44
|
+
/**
|
|
45
|
+
* Helper method to configure a filter for private events
|
|
46
|
+
* @param filter - The original filter
|
|
47
|
+
* @param forcePrivateOnly - Whether to force filtering for only PrivateEvents
|
|
48
|
+
* @returns The configured filter with proper topics
|
|
49
|
+
*/
|
|
50
|
+
private configurePrivateEventsFilter;
|
|
51
|
+
/**
|
|
52
|
+
* Gets logs for private events, including authentication headers
|
|
53
|
+
* @param filter - The filter parameters for logs
|
|
54
|
+
* @returns Array of logs matching the filter
|
|
55
|
+
*/
|
|
56
|
+
getAllLogs(filter?: PrivateEventsFilter): Promise<Array<Log>>;
|
|
57
|
+
/**
|
|
58
|
+
* Gets only private events (PrivateEvent logs), including authentication headers
|
|
59
|
+
* @param filter - The filter parameters for logs
|
|
60
|
+
* @returns Array of logs matching the filter, containing only PrivateEvent logs
|
|
61
|
+
*/
|
|
62
|
+
getPrivateLogs(filter?: PrivateEventsFilter): Promise<Log[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Override of ethers' getLogs method that preserves our custom _isPrivateEvent property
|
|
65
|
+
*
|
|
66
|
+
* IMPORTANT: This method mimics the behavior of ethers' original getLogs implementation
|
|
67
|
+
* but adds a crucial step to preserve the _isPrivateEvent flag. We need this because:
|
|
68
|
+
*
|
|
69
|
+
* 1. Ethers' _getFilter method sanitizes filter objects, removing any non-standard properties
|
|
70
|
+
* 2. Our _isPrivateEvent flag would be stripped by this sanitization
|
|
71
|
+
* 3. We need the flag to reach the _send method to trigger the addition of auth headers
|
|
72
|
+
*
|
|
73
|
+
* The approach here is to run the normal filter processing, then re-attach our flag as a
|
|
74
|
+
* non-enumerable property to avoid JSON serialization issues. This allows the flag to
|
|
75
|
+
* survive until _send where we check for it to determine if auth headers are needed.
|
|
76
|
+
*
|
|
77
|
+
* @param _filter - The filter with our potential _isPrivateEvent property
|
|
78
|
+
* @returns Array of logs matching the filter
|
|
79
|
+
*/
|
|
80
|
+
getLogs(_filter: PrivateEventsFilter | FilterByBlockHash): Promise<Log[]>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Extended LogDescription type that includes private event details
|
|
85
|
+
*/
|
|
86
|
+
interface SDLogDescription extends LogDescription {
|
|
87
|
+
/**
|
|
88
|
+
* Only present for PrivateEvents - contains the decoded inner log
|
|
89
|
+
* If decoding failed, this will be null
|
|
90
|
+
*/
|
|
91
|
+
innerLog?: LogDescription | null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Extends ethers Interface to provide support for decoding PrivateEvent logs
|
|
95
|
+
* Make sure to include the PrivateEvent signature in your ABI when using this class
|
|
96
|
+
*/
|
|
97
|
+
declare class SDInterface extends Interface {
|
|
98
|
+
/**
|
|
99
|
+
* Extends the parseLog method to handle PrivateEvent logs
|
|
100
|
+
* @param log - The log to parse
|
|
101
|
+
* @returns The parsed log description with additional private event details if applicable
|
|
102
|
+
*/
|
|
103
|
+
parseLog(log: Parameters<Interface['parseLog']>[0]): SDLogDescription | null;
|
|
25
104
|
}
|
|
26
105
|
|
|
27
|
-
export { SIGN_RPC_METHODS, SilentDataRollupProvider, type SilentDataRollupProviderConfig };
|
|
106
|
+
export { DEBUG_NAMESPACE, type PrivateEventsFilter, SDInterface, type SDLogDescription, SIGN_RPC_METHODS, SilentDataRollupProvider, type SilentDataRollupProviderConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,11 +17,21 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
33
|
+
DEBUG_NAMESPACE: () => DEBUG_NAMESPACE,
|
|
34
|
+
SDInterface: () => SDInterface,
|
|
23
35
|
SIGN_RPC_METHODS: () => SIGN_RPC_METHODS,
|
|
24
36
|
SilentDataRollupProvider: () => SilentDataRollupProvider
|
|
25
37
|
});
|
|
@@ -33,10 +45,14 @@ var SIGN_RPC_METHODS = [
|
|
|
33
45
|
"eth_getProof",
|
|
34
46
|
"eth_getTransactionReceipt"
|
|
35
47
|
];
|
|
48
|
+
var DEBUG_NAMESPACE = "silentdata:ethers-provider";
|
|
36
49
|
|
|
37
50
|
// src/provider.ts
|
|
38
51
|
var import_silentdatarollup_core = require("@appliedblockchain/silentdatarollup-core");
|
|
39
52
|
var import_ethers = require("ethers");
|
|
53
|
+
function isPromise(value) {
|
|
54
|
+
return value && typeof value.then === "function";
|
|
55
|
+
}
|
|
40
56
|
function getNetwork(name, chainId) {
|
|
41
57
|
switch (name) {
|
|
42
58
|
case import_silentdatarollup_core.NetworkName.MAINNET:
|
|
@@ -89,16 +105,28 @@ var SilentDataRollupProvider = class _SilentDataRollupProvider extends import_et
|
|
|
89
105
|
if (Array.isArray(payload)) {
|
|
90
106
|
throw new Error("Batch requests are not currently supported");
|
|
91
107
|
}
|
|
92
|
-
|
|
108
|
+
const isEthCallOrEstimateGas = payload.method === "eth_call" || payload.method === "eth_estimateGas";
|
|
109
|
+
if (isEthCallOrEstimateGas && Array.isArray(payload.params)) {
|
|
93
110
|
const txParams = payload.params[0];
|
|
94
111
|
if (typeof txParams === "object" && txParams !== null) {
|
|
95
112
|
txParams.from = await this.signer.getAddress();
|
|
96
113
|
}
|
|
97
114
|
}
|
|
115
|
+
let isPrivateLogsRequest = false;
|
|
116
|
+
if (payload.method === "eth_getLogs" && Array.isArray(payload.params) && payload.params.length > 0) {
|
|
117
|
+
const filter = payload.params[0];
|
|
118
|
+
if (filter && typeof filter === "object" && "_isPrivateEvent" in filter) {
|
|
119
|
+
isPrivateLogsRequest = !!filter._isPrivateEvent;
|
|
120
|
+
if (isPrivateLogsRequest) {
|
|
121
|
+
const { _isPrivateEvent, ...filterCopy } = filter;
|
|
122
|
+
payload.params[0] = filterCopy;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
98
126
|
const request = this._getConnection();
|
|
99
127
|
request.body = JSON.stringify(payload);
|
|
100
128
|
request.setHeader("content-type", "application/json");
|
|
101
|
-
const requiresAuthHeaders = import_silentdatarollup_core.SIGN_RPC_METHODS.includes(payload.method) || (0, import_silentdatarollup_core.isSignableContractCall)(
|
|
129
|
+
const requiresAuthHeaders = isPrivateLogsRequest || import_silentdatarollup_core.SIGN_RPC_METHODS.includes(payload.method) || (0, import_silentdatarollup_core.isSignableContractCall)(
|
|
102
130
|
payload,
|
|
103
131
|
this.baseProvider.contractMethodsToSign,
|
|
104
132
|
this.baseProvider.contract
|
|
@@ -151,9 +179,172 @@ var SilentDataRollupProvider = class _SilentDataRollupProvider extends import_et
|
|
|
151
179
|
const clonedProvider = new _SilentDataRollupProvider(this.config);
|
|
152
180
|
return clonedProvider;
|
|
153
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Helper method to configure a filter for private events
|
|
184
|
+
* @param filter - The original filter
|
|
185
|
+
* @param forcePrivateOnly - Whether to force filtering for only PrivateEvents
|
|
186
|
+
* @returns The configured filter with proper topics
|
|
187
|
+
*/
|
|
188
|
+
configurePrivateEventsFilter(filter, forcePrivateOnly = false) {
|
|
189
|
+
const privateFilter = {
|
|
190
|
+
...filter,
|
|
191
|
+
_isPrivateEvent: true
|
|
192
|
+
};
|
|
193
|
+
privateFilter.topics = privateFilter.topics || [];
|
|
194
|
+
if (forcePrivateOnly || privateFilter.eventSignature) {
|
|
195
|
+
if (forcePrivateOnly) {
|
|
196
|
+
privateFilter.topics = [
|
|
197
|
+
import_silentdatarollup_core.PRIVATE_EVENT_SIGNATURE_HASH,
|
|
198
|
+
// Only match PrivateEvent
|
|
199
|
+
...privateFilter.topics.slice(1)
|
|
200
|
+
// Preserve any other topic filters
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
if (privateFilter.eventSignature) {
|
|
204
|
+
const eventTypeHash = (0, import_silentdatarollup_core.calculateEventTypeHash)(
|
|
205
|
+
privateFilter.eventSignature
|
|
206
|
+
);
|
|
207
|
+
if (forcePrivateOnly) {
|
|
208
|
+
privateFilter.topics[1] = eventTypeHash;
|
|
209
|
+
} else {
|
|
210
|
+
privateFilter.topics = [
|
|
211
|
+
import_silentdatarollup_core.PRIVATE_EVENT_SIGNATURE_HASH,
|
|
212
|
+
// Only match PrivateEvent
|
|
213
|
+
eventTypeHash,
|
|
214
|
+
// Only match the specific event type
|
|
215
|
+
...(privateFilter.topics || []).slice(2)
|
|
216
|
+
// Preserve any other topics
|
|
217
|
+
];
|
|
218
|
+
}
|
|
219
|
+
delete privateFilter.eventSignature;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return privateFilter;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Gets logs for private events, including authentication headers
|
|
226
|
+
* @param filter - The filter parameters for logs
|
|
227
|
+
* @returns Array of logs matching the filter
|
|
228
|
+
*/
|
|
229
|
+
async getAllLogs(filter = {}) {
|
|
230
|
+
const privateFilter = this.configurePrivateEventsFilter(filter, false);
|
|
231
|
+
return await this.getLogs(privateFilter);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Gets only private events (PrivateEvent logs), including authentication headers
|
|
235
|
+
* @param filter - The filter parameters for logs
|
|
236
|
+
* @returns Array of logs matching the filter, containing only PrivateEvent logs
|
|
237
|
+
*/
|
|
238
|
+
async getPrivateLogs(filter = {}) {
|
|
239
|
+
const privateFilter = this.configurePrivateEventsFilter(filter, true);
|
|
240
|
+
return await this.getLogs(privateFilter);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Override of ethers' getLogs method that preserves our custom _isPrivateEvent property
|
|
244
|
+
*
|
|
245
|
+
* IMPORTANT: This method mimics the behavior of ethers' original getLogs implementation
|
|
246
|
+
* but adds a crucial step to preserve the _isPrivateEvent flag. We need this because:
|
|
247
|
+
*
|
|
248
|
+
* 1. Ethers' _getFilter method sanitizes filter objects, removing any non-standard properties
|
|
249
|
+
* 2. Our _isPrivateEvent flag would be stripped by this sanitization
|
|
250
|
+
* 3. We need the flag to reach the _send method to trigger the addition of auth headers
|
|
251
|
+
*
|
|
252
|
+
* The approach here is to run the normal filter processing, then re-attach our flag as a
|
|
253
|
+
* non-enumerable property to avoid JSON serialization issues. This allows the flag to
|
|
254
|
+
* survive until _send where we check for it to determine if auth headers are needed.
|
|
255
|
+
*
|
|
256
|
+
* @param _filter - The filter with our potential _isPrivateEvent property
|
|
257
|
+
* @returns Array of logs matching the filter
|
|
258
|
+
*/
|
|
259
|
+
async getLogs(_filter) {
|
|
260
|
+
let filter = this._getFilter(_filter);
|
|
261
|
+
if (isPromise(filter)) {
|
|
262
|
+
filter = await filter;
|
|
263
|
+
}
|
|
264
|
+
if (typeof _filter === "object" && "_isPrivateEvent" in _filter && _filter._isPrivateEvent) {
|
|
265
|
+
Object.defineProperty(filter, "_isPrivateEvent", {
|
|
266
|
+
value: true,
|
|
267
|
+
enumerable: false
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
const { network, params } = await (0, import_ethers.resolveProperties)({
|
|
271
|
+
network: this.getNetwork(),
|
|
272
|
+
params: this._perform({ method: "getLogs", filter })
|
|
273
|
+
});
|
|
274
|
+
return params.map((p) => this._wrapLog(p, network));
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// src/sdInterface.ts
|
|
279
|
+
var import_debug = __toESM(require("debug"));
|
|
280
|
+
var import_ethers2 = require("ethers");
|
|
281
|
+
var debugLog = (0, import_debug.default)(DEBUG_NAMESPACE);
|
|
282
|
+
var SDInterface = class extends import_ethers2.Interface {
|
|
283
|
+
/**
|
|
284
|
+
* Extends the parseLog method to handle PrivateEvent logs
|
|
285
|
+
* @param log - The log to parse
|
|
286
|
+
* @returns The parsed log description with additional private event details if applicable
|
|
287
|
+
*/
|
|
288
|
+
parseLog(log) {
|
|
289
|
+
const parsedLog = super.parseLog(log);
|
|
290
|
+
if (!parsedLog) {
|
|
291
|
+
debugLog(
|
|
292
|
+
"Failed to parse log - no matching event found or event is anonymous"
|
|
293
|
+
);
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
if (parsedLog.name === "PrivateEvent") {
|
|
297
|
+
debugLog("Processing PrivateEvent log");
|
|
298
|
+
const eventType = parsedLog.args.eventType;
|
|
299
|
+
const payload = parsedLog.args.payload;
|
|
300
|
+
debugLog(
|
|
301
|
+
`PrivateEvent - eventType: ${eventType}, payload length: ${payload?.length || 0}`
|
|
302
|
+
);
|
|
303
|
+
parsedLog.innerLog = null;
|
|
304
|
+
try {
|
|
305
|
+
if (!payload || payload === "0x") {
|
|
306
|
+
debugLog("Empty payload for PrivateEvent, cannot decode inner log");
|
|
307
|
+
return parsedLog;
|
|
308
|
+
}
|
|
309
|
+
const syntheticLog = {
|
|
310
|
+
topics: [eventType],
|
|
311
|
+
data: payload
|
|
312
|
+
};
|
|
313
|
+
debugLog(`Created synthetic log with topic: ${eventType}`);
|
|
314
|
+
const eventFragment = this.getEvent(eventType);
|
|
315
|
+
if (!eventFragment) {
|
|
316
|
+
debugLog(`No matching event found for topic ${eventType}`);
|
|
317
|
+
return parsedLog;
|
|
318
|
+
}
|
|
319
|
+
debugLog(`Found matching event fragment: ${eventFragment.name}`);
|
|
320
|
+
try {
|
|
321
|
+
const innerLogDescription = super.parseLog(syntheticLog);
|
|
322
|
+
if (innerLogDescription) {
|
|
323
|
+
debugLog(
|
|
324
|
+
`Successfully decoded inner log: ${innerLogDescription.name}`
|
|
325
|
+
);
|
|
326
|
+
parsedLog.innerLog = innerLogDescription;
|
|
327
|
+
} else {
|
|
328
|
+
debugLog(
|
|
329
|
+
"Failed to parse inner log - no matching inner event found"
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
} catch (innerError) {
|
|
333
|
+
debugLog(`Failed to parse synthetic log for inner log:`, innerError);
|
|
334
|
+
}
|
|
335
|
+
} catch (error) {
|
|
336
|
+
debugLog(`Failed to decode private event payload:`, error);
|
|
337
|
+
}
|
|
338
|
+
} else {
|
|
339
|
+
debugLog(`Processing regular event: ${parsedLog.name}`);
|
|
340
|
+
}
|
|
341
|
+
return parsedLog;
|
|
342
|
+
}
|
|
154
343
|
};
|
|
155
344
|
// Annotate the CommonJS export names for ESM import in node:
|
|
156
345
|
0 && (module.exports = {
|
|
346
|
+
DEBUG_NAMESPACE,
|
|
347
|
+
SDInterface,
|
|
157
348
|
SIGN_RPC_METHODS,
|
|
158
349
|
SilentDataRollupProvider
|
|
159
350
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -6,9 +6,11 @@ var SIGN_RPC_METHODS = [
|
|
|
6
6
|
"eth_getProof",
|
|
7
7
|
"eth_getTransactionReceipt"
|
|
8
8
|
];
|
|
9
|
+
var DEBUG_NAMESPACE = "silentdata:ethers-provider";
|
|
9
10
|
|
|
10
11
|
// src/provider.ts
|
|
11
12
|
import {
|
|
13
|
+
calculateEventTypeHash,
|
|
12
14
|
ChainId,
|
|
13
15
|
HEADER_DELEGATE,
|
|
14
16
|
HEADER_DELEGATE_SIGNATURE,
|
|
@@ -18,6 +20,7 @@ import {
|
|
|
18
20
|
HEADER_TIMESTAMP,
|
|
19
21
|
isSignableContractCall,
|
|
20
22
|
NetworkName,
|
|
23
|
+
PRIVATE_EVENT_SIGNATURE_HASH,
|
|
21
24
|
SIGN_RPC_METHODS as SIGN_RPC_METHODS2,
|
|
22
25
|
SignatureType,
|
|
23
26
|
SilentDataRollupBase
|
|
@@ -27,8 +30,12 @@ import {
|
|
|
27
30
|
FetchRequest,
|
|
28
31
|
JsonRpcProvider,
|
|
29
32
|
Network,
|
|
33
|
+
resolveProperties,
|
|
30
34
|
Wallet
|
|
31
35
|
} from "ethers";
|
|
36
|
+
function isPromise(value) {
|
|
37
|
+
return value && typeof value.then === "function";
|
|
38
|
+
}
|
|
32
39
|
function getNetwork(name, chainId) {
|
|
33
40
|
switch (name) {
|
|
34
41
|
case NetworkName.MAINNET:
|
|
@@ -81,16 +88,28 @@ var SilentDataRollupProvider = class _SilentDataRollupProvider extends JsonRpcPr
|
|
|
81
88
|
if (Array.isArray(payload)) {
|
|
82
89
|
throw new Error("Batch requests are not currently supported");
|
|
83
90
|
}
|
|
84
|
-
|
|
91
|
+
const isEthCallOrEstimateGas = payload.method === "eth_call" || payload.method === "eth_estimateGas";
|
|
92
|
+
if (isEthCallOrEstimateGas && Array.isArray(payload.params)) {
|
|
85
93
|
const txParams = payload.params[0];
|
|
86
94
|
if (typeof txParams === "object" && txParams !== null) {
|
|
87
95
|
txParams.from = await this.signer.getAddress();
|
|
88
96
|
}
|
|
89
97
|
}
|
|
98
|
+
let isPrivateLogsRequest = false;
|
|
99
|
+
if (payload.method === "eth_getLogs" && Array.isArray(payload.params) && payload.params.length > 0) {
|
|
100
|
+
const filter = payload.params[0];
|
|
101
|
+
if (filter && typeof filter === "object" && "_isPrivateEvent" in filter) {
|
|
102
|
+
isPrivateLogsRequest = !!filter._isPrivateEvent;
|
|
103
|
+
if (isPrivateLogsRequest) {
|
|
104
|
+
const { _isPrivateEvent, ...filterCopy } = filter;
|
|
105
|
+
payload.params[0] = filterCopy;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
90
109
|
const request = this._getConnection();
|
|
91
110
|
request.body = JSON.stringify(payload);
|
|
92
111
|
request.setHeader("content-type", "application/json");
|
|
93
|
-
const requiresAuthHeaders = SIGN_RPC_METHODS2.includes(payload.method) || isSignableContractCall(
|
|
112
|
+
const requiresAuthHeaders = isPrivateLogsRequest || SIGN_RPC_METHODS2.includes(payload.method) || isSignableContractCall(
|
|
94
113
|
payload,
|
|
95
114
|
this.baseProvider.contractMethodsToSign,
|
|
96
115
|
this.baseProvider.contract
|
|
@@ -143,8 +162,171 @@ var SilentDataRollupProvider = class _SilentDataRollupProvider extends JsonRpcPr
|
|
|
143
162
|
const clonedProvider = new _SilentDataRollupProvider(this.config);
|
|
144
163
|
return clonedProvider;
|
|
145
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Helper method to configure a filter for private events
|
|
167
|
+
* @param filter - The original filter
|
|
168
|
+
* @param forcePrivateOnly - Whether to force filtering for only PrivateEvents
|
|
169
|
+
* @returns The configured filter with proper topics
|
|
170
|
+
*/
|
|
171
|
+
configurePrivateEventsFilter(filter, forcePrivateOnly = false) {
|
|
172
|
+
const privateFilter = {
|
|
173
|
+
...filter,
|
|
174
|
+
_isPrivateEvent: true
|
|
175
|
+
};
|
|
176
|
+
privateFilter.topics = privateFilter.topics || [];
|
|
177
|
+
if (forcePrivateOnly || privateFilter.eventSignature) {
|
|
178
|
+
if (forcePrivateOnly) {
|
|
179
|
+
privateFilter.topics = [
|
|
180
|
+
PRIVATE_EVENT_SIGNATURE_HASH,
|
|
181
|
+
// Only match PrivateEvent
|
|
182
|
+
...privateFilter.topics.slice(1)
|
|
183
|
+
// Preserve any other topic filters
|
|
184
|
+
];
|
|
185
|
+
}
|
|
186
|
+
if (privateFilter.eventSignature) {
|
|
187
|
+
const eventTypeHash = calculateEventTypeHash(
|
|
188
|
+
privateFilter.eventSignature
|
|
189
|
+
);
|
|
190
|
+
if (forcePrivateOnly) {
|
|
191
|
+
privateFilter.topics[1] = eventTypeHash;
|
|
192
|
+
} else {
|
|
193
|
+
privateFilter.topics = [
|
|
194
|
+
PRIVATE_EVENT_SIGNATURE_HASH,
|
|
195
|
+
// Only match PrivateEvent
|
|
196
|
+
eventTypeHash,
|
|
197
|
+
// Only match the specific event type
|
|
198
|
+
...(privateFilter.topics || []).slice(2)
|
|
199
|
+
// Preserve any other topics
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
delete privateFilter.eventSignature;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return privateFilter;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Gets logs for private events, including authentication headers
|
|
209
|
+
* @param filter - The filter parameters for logs
|
|
210
|
+
* @returns Array of logs matching the filter
|
|
211
|
+
*/
|
|
212
|
+
async getAllLogs(filter = {}) {
|
|
213
|
+
const privateFilter = this.configurePrivateEventsFilter(filter, false);
|
|
214
|
+
return await this.getLogs(privateFilter);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Gets only private events (PrivateEvent logs), including authentication headers
|
|
218
|
+
* @param filter - The filter parameters for logs
|
|
219
|
+
* @returns Array of logs matching the filter, containing only PrivateEvent logs
|
|
220
|
+
*/
|
|
221
|
+
async getPrivateLogs(filter = {}) {
|
|
222
|
+
const privateFilter = this.configurePrivateEventsFilter(filter, true);
|
|
223
|
+
return await this.getLogs(privateFilter);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Override of ethers' getLogs method that preserves our custom _isPrivateEvent property
|
|
227
|
+
*
|
|
228
|
+
* IMPORTANT: This method mimics the behavior of ethers' original getLogs implementation
|
|
229
|
+
* but adds a crucial step to preserve the _isPrivateEvent flag. We need this because:
|
|
230
|
+
*
|
|
231
|
+
* 1. Ethers' _getFilter method sanitizes filter objects, removing any non-standard properties
|
|
232
|
+
* 2. Our _isPrivateEvent flag would be stripped by this sanitization
|
|
233
|
+
* 3. We need the flag to reach the _send method to trigger the addition of auth headers
|
|
234
|
+
*
|
|
235
|
+
* The approach here is to run the normal filter processing, then re-attach our flag as a
|
|
236
|
+
* non-enumerable property to avoid JSON serialization issues. This allows the flag to
|
|
237
|
+
* survive until _send where we check for it to determine if auth headers are needed.
|
|
238
|
+
*
|
|
239
|
+
* @param _filter - The filter with our potential _isPrivateEvent property
|
|
240
|
+
* @returns Array of logs matching the filter
|
|
241
|
+
*/
|
|
242
|
+
async getLogs(_filter) {
|
|
243
|
+
let filter = this._getFilter(_filter);
|
|
244
|
+
if (isPromise(filter)) {
|
|
245
|
+
filter = await filter;
|
|
246
|
+
}
|
|
247
|
+
if (typeof _filter === "object" && "_isPrivateEvent" in _filter && _filter._isPrivateEvent) {
|
|
248
|
+
Object.defineProperty(filter, "_isPrivateEvent", {
|
|
249
|
+
value: true,
|
|
250
|
+
enumerable: false
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const { network, params } = await resolveProperties({
|
|
254
|
+
network: this.getNetwork(),
|
|
255
|
+
params: this._perform({ method: "getLogs", filter })
|
|
256
|
+
});
|
|
257
|
+
return params.map((p) => this._wrapLog(p, network));
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// src/sdInterface.ts
|
|
262
|
+
import debug from "debug";
|
|
263
|
+
import { Interface } from "ethers";
|
|
264
|
+
var debugLog = debug(DEBUG_NAMESPACE);
|
|
265
|
+
var SDInterface = class extends Interface {
|
|
266
|
+
/**
|
|
267
|
+
* Extends the parseLog method to handle PrivateEvent logs
|
|
268
|
+
* @param log - The log to parse
|
|
269
|
+
* @returns The parsed log description with additional private event details if applicable
|
|
270
|
+
*/
|
|
271
|
+
parseLog(log) {
|
|
272
|
+
const parsedLog = super.parseLog(log);
|
|
273
|
+
if (!parsedLog) {
|
|
274
|
+
debugLog(
|
|
275
|
+
"Failed to parse log - no matching event found or event is anonymous"
|
|
276
|
+
);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
if (parsedLog.name === "PrivateEvent") {
|
|
280
|
+
debugLog("Processing PrivateEvent log");
|
|
281
|
+
const eventType = parsedLog.args.eventType;
|
|
282
|
+
const payload = parsedLog.args.payload;
|
|
283
|
+
debugLog(
|
|
284
|
+
`PrivateEvent - eventType: ${eventType}, payload length: ${payload?.length || 0}`
|
|
285
|
+
);
|
|
286
|
+
parsedLog.innerLog = null;
|
|
287
|
+
try {
|
|
288
|
+
if (!payload || payload === "0x") {
|
|
289
|
+
debugLog("Empty payload for PrivateEvent, cannot decode inner log");
|
|
290
|
+
return parsedLog;
|
|
291
|
+
}
|
|
292
|
+
const syntheticLog = {
|
|
293
|
+
topics: [eventType],
|
|
294
|
+
data: payload
|
|
295
|
+
};
|
|
296
|
+
debugLog(`Created synthetic log with topic: ${eventType}`);
|
|
297
|
+
const eventFragment = this.getEvent(eventType);
|
|
298
|
+
if (!eventFragment) {
|
|
299
|
+
debugLog(`No matching event found for topic ${eventType}`);
|
|
300
|
+
return parsedLog;
|
|
301
|
+
}
|
|
302
|
+
debugLog(`Found matching event fragment: ${eventFragment.name}`);
|
|
303
|
+
try {
|
|
304
|
+
const innerLogDescription = super.parseLog(syntheticLog);
|
|
305
|
+
if (innerLogDescription) {
|
|
306
|
+
debugLog(
|
|
307
|
+
`Successfully decoded inner log: ${innerLogDescription.name}`
|
|
308
|
+
);
|
|
309
|
+
parsedLog.innerLog = innerLogDescription;
|
|
310
|
+
} else {
|
|
311
|
+
debugLog(
|
|
312
|
+
"Failed to parse inner log - no matching inner event found"
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
} catch (innerError) {
|
|
316
|
+
debugLog(`Failed to parse synthetic log for inner log:`, innerError);
|
|
317
|
+
}
|
|
318
|
+
} catch (error) {
|
|
319
|
+
debugLog(`Failed to decode private event payload:`, error);
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
debugLog(`Processing regular event: ${parsedLog.name}`);
|
|
323
|
+
}
|
|
324
|
+
return parsedLog;
|
|
325
|
+
}
|
|
146
326
|
};
|
|
147
327
|
export {
|
|
328
|
+
DEBUG_NAMESPACE,
|
|
329
|
+
SDInterface,
|
|
148
330
|
SIGN_RPC_METHODS,
|
|
149
331
|
SilentDataRollupProvider
|
|
150
332
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appliedblockchain/silentdatarollup-ethers-provider",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Ethers.js provider for Silent Data [Rollup]",
|
|
5
5
|
"author": "Applied Blockchain",
|
|
6
6
|
"homepage": "https://github.com/appliedblockchain/silent-data-rollup-providers#readme",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"test": "jest"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@appliedblockchain/silentdatarollup-core": "1.0.
|
|
35
|
+
"@appliedblockchain/silentdatarollup-core": "1.0.3",
|
|
36
|
+
"debug": "4.3.7",
|
|
36
37
|
"ethers": "6.13.2"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|