@interfold/sdk 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -35
- package/dist/events/index.cjs +162 -7
- package/dist/events/index.cjs.map +1 -1
- package/dist/events/index.d.ts +48 -1
- package/dist/events/index.js +162 -8
- package/dist/events/index.js.map +1 -1
- package/dist/index.cjs +171 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +171 -8
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ pnpm add @interfold/sdk
|
|
|
24
24
|
## Quick Start
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
|
-
import { InterfoldSDK, InterfoldEventType, RegistryEventType } from '@interfold/sdk'
|
|
27
|
+
import { CommitteeSize, InterfoldSDK, InterfoldEventType, RegistryEventType } from '@interfold/sdk'
|
|
28
28
|
import { createPublicClient, createWalletClient, http, custom } from 'viem'
|
|
29
29
|
import { sepolia } from 'viem/chains'
|
|
30
30
|
|
|
@@ -49,8 +49,8 @@ const sdk = new InterfoldSDK({
|
|
|
49
49
|
feeToken: '0x...', // Your ERC-20 fee token address
|
|
50
50
|
},
|
|
51
51
|
chain: sepolia,
|
|
52
|
-
//
|
|
53
|
-
thresholdBfvParamsPresetName: '
|
|
52
|
+
// 'INSECURE_THRESHOLD_512' for local dev and Sepolia; 'SECURE_THRESHOLD_8192' for production
|
|
53
|
+
thresholdBfvParamsPresetName: 'INSECURE_THRESHOLD_512',
|
|
54
54
|
})
|
|
55
55
|
|
|
56
56
|
// Listen to events with the unified event system
|
|
@@ -58,19 +58,24 @@ sdk.onInterfoldEvent(InterfoldEventType.E3_REQUESTED, (event) => {
|
|
|
58
58
|
console.log('E3 Requested:', event.data)
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
sdk.onInterfoldEvent(RegistryEventType.
|
|
62
|
-
console.log('Committee
|
|
61
|
+
sdk.onInterfoldEvent(RegistryEventType.COMMITTEE_RANDOMNESS_REQUESTED, (event) => {
|
|
62
|
+
console.log('Committee randomness requested:', event.data)
|
|
63
63
|
})
|
|
64
64
|
|
|
65
65
|
// Interact with contracts
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
const now = BigInt(Math.floor(Date.now() / 1000))
|
|
67
|
+
const requestParams = {
|
|
68
|
+
committeeSize: CommitteeSize.Minimum,
|
|
69
|
+
inputWindow: [now, now + 300n] as const,
|
|
69
70
|
e3Program: '0x...',
|
|
70
|
-
|
|
71
|
+
paramSet: 0, // Insecure512 for development
|
|
71
72
|
computeProviderParams: '0x...',
|
|
72
73
|
customParams: '0x...',
|
|
73
|
-
}
|
|
74
|
+
}
|
|
75
|
+
const quote = await sdk.getE3Quote(requestParams)
|
|
76
|
+
const approvalHash = await sdk.approveFeeToken(quote)
|
|
77
|
+
await sdk.waitForTransaction(approvalHash)
|
|
78
|
+
const hash = await sdk.requestE3({ ...requestParams, maxFee: quote })
|
|
74
79
|
```
|
|
75
80
|
|
|
76
81
|
### Factory Method
|
|
@@ -90,8 +95,8 @@ const sdk = InterfoldSDK.create({
|
|
|
90
95
|
},
|
|
91
96
|
chain: sepolia,
|
|
92
97
|
privateKey: '0x...', // optional — omit for read-only
|
|
93
|
-
//
|
|
94
|
-
thresholdBfvParamsPresetName: '
|
|
98
|
+
// 'INSECURE_THRESHOLD_512' for local dev and Sepolia; 'SECURE_THRESHOLD_8192' for production
|
|
99
|
+
thresholdBfvParamsPresetName: 'INSECURE_THRESHOLD_512',
|
|
95
100
|
})
|
|
96
101
|
```
|
|
97
102
|
|
|
@@ -137,17 +142,15 @@ enum InterfoldEventType {
|
|
|
137
142
|
PLAINTEXT_OUTPUT_PUBLISHED = 'PlaintextOutputPublished',
|
|
138
143
|
|
|
139
144
|
// E3 Program Management
|
|
140
|
-
|
|
141
|
-
E3_PROGRAM_DISABLED = 'E3ProgramDisabled',
|
|
145
|
+
E3_PROGRAM_REGISTERED = 'E3ProgramRegistered',
|
|
142
146
|
|
|
143
147
|
// Encryption Scheme Management
|
|
144
148
|
ENCRYPTION_SCHEME_ENABLED = 'EncryptionSchemeEnabled',
|
|
145
|
-
ENCRYPTION_SCHEME_DISABLED = 'EncryptionSchemeDisabled',
|
|
146
149
|
|
|
147
150
|
// Configuration
|
|
148
151
|
CIPHERNODE_REGISTRY_SET = 'CiphernodeRegistrySet',
|
|
149
152
|
MAX_DURATION_SET = 'MaxDurationSet',
|
|
150
|
-
|
|
153
|
+
PARAM_SET_REGISTERED = 'ParamSetRegistered',
|
|
151
154
|
OWNERSHIP_TRANSFERRED = 'OwnershipTransferred',
|
|
152
155
|
INITIALIZED = 'Initialized',
|
|
153
156
|
}
|
|
@@ -157,15 +160,45 @@ enum InterfoldEventType {
|
|
|
157
160
|
|
|
158
161
|
```typescript
|
|
159
162
|
enum RegistryEventType {
|
|
163
|
+
// On-chain legacy event retained only for pre-VRF registry logs. The
|
|
164
|
+
// ciphernode runtime creates its separate durable CommitteeRequested event
|
|
165
|
+
// after the Registry accepts a VRF response.
|
|
160
166
|
COMMITTEE_REQUESTED = 'CommitteeRequested',
|
|
167
|
+
COMMITTEE_RANDOMNESS_REQUESTED = 'CommitteeRandomnessRequested',
|
|
168
|
+
RANDOMNESS_CIRCUIT_BREAKER_TRIPPED = 'RandomnessCircuitBreakerTripped',
|
|
161
169
|
COMMITTEE_PUBLISHED = 'CommitteePublished',
|
|
162
|
-
COMMITTEE_FINALIZED = '
|
|
170
|
+
COMMITTEE_FINALIZED = 'SortitionCommitteeFinalized',
|
|
163
171
|
INTERFOLD_SET = 'InterfoldSet',
|
|
164
172
|
OWNERSHIP_TRANSFERRED = 'OwnershipTransferred',
|
|
165
173
|
INITIALIZED = 'Initialized',
|
|
166
174
|
}
|
|
167
175
|
```
|
|
168
176
|
|
|
177
|
+
### Randomness Provider Events
|
|
178
|
+
|
|
179
|
+
The provider address is frozen for each E3 and can change after governance rotation, so it is not
|
|
180
|
+
part of the static SDK contract addresses. Read `provider`, `requestId`, and `e3Id` from
|
|
181
|
+
`CommitteeRandomnessRequested`, then watch that provider through the main SDK:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
await sdk.onRandomnessProviderEvent(
|
|
185
|
+
provider,
|
|
186
|
+
RandomnessProviderEventType.RANDOMNESS_FULFILLED,
|
|
187
|
+
({ data }) => {
|
|
188
|
+
console.log(data.requestId, data.e3Id, data.fulfilledAt)
|
|
189
|
+
},
|
|
190
|
+
)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Use `sdk.getHistoricalRandomnessProviderEvents` with explicit block bounds to recover earlier
|
|
194
|
+
fulfillments. Start the live watcher at `historicalToBlock + 1n` so the historical and live ranges
|
|
195
|
+
do not overlap. Historical reads are split into bounded RPC queries, and live watchers suppress
|
|
196
|
+
duplicate delivery of the same log. `RandomnessFulfilled` proves that the provider stored a
|
|
197
|
+
response. The Registry remains authoritative about whether that response was timely and usable. If
|
|
198
|
+
the listener config does not define `fromBlock`, the history method requires it as an argument.
|
|
199
|
+
Subscribers that share one provider and event watcher must use the same explicit `fromBlock`, or
|
|
200
|
+
omit it to join the active watcher.
|
|
201
|
+
|
|
169
202
|
### Event Data Structure
|
|
170
203
|
|
|
171
204
|
Each event follows a consistent structure:
|
|
@@ -209,8 +242,8 @@ function MyComponent() {
|
|
|
209
242
|
feeToken: '0x...',
|
|
210
243
|
},
|
|
211
244
|
autoConnect: true,
|
|
212
|
-
//
|
|
213
|
-
thresholdBfvParamsPresetName: '
|
|
245
|
+
// 'INSECURE_THRESHOLD_512' for local dev and Sepolia; 'SECURE_THRESHOLD_8192' for production
|
|
246
|
+
thresholdBfvParamsPresetName: 'INSECURE_THRESHOLD_512',
|
|
214
247
|
})
|
|
215
248
|
|
|
216
249
|
useEffect(() => {
|
|
@@ -272,8 +305,8 @@ import {
|
|
|
272
305
|
getThresholdBfvParamsSet,
|
|
273
306
|
} from '@interfold/sdk'
|
|
274
307
|
|
|
275
|
-
//
|
|
276
|
-
const presetName = '
|
|
308
|
+
// 'INSECURE_THRESHOLD_512' for local dev and Sepolia; 'SECURE_THRESHOLD_8192' for production
|
|
309
|
+
const presetName = 'INSECURE_THRESHOLD_512'
|
|
277
310
|
|
|
278
311
|
const publicKey = await generatePublicKey(presetName)
|
|
279
312
|
const encrypted = await encryptNumber(42n, publicKey, presetName)
|
|
@@ -311,13 +344,14 @@ await sdk.approveFeeToken(amount: bigint);
|
|
|
311
344
|
|
|
312
345
|
// Request a new E3 computation
|
|
313
346
|
await sdk.requestE3({
|
|
314
|
-
|
|
347
|
+
committeeSize: CommitteeSize.Minimum,
|
|
315
348
|
inputWindow: [bigint, bigint],
|
|
316
349
|
e3Program: `0x${string}`,
|
|
317
|
-
|
|
350
|
+
paramSet: 0,
|
|
318
351
|
computeProviderParams: `0x${string}`,
|
|
319
|
-
customParams
|
|
320
|
-
|
|
352
|
+
customParams: '0x',
|
|
353
|
+
maxFee: amount,
|
|
354
|
+
gasLimit: 1_500_000n
|
|
321
355
|
});
|
|
322
356
|
|
|
323
357
|
// Publish ciphertext output
|
|
@@ -331,9 +365,9 @@ const stage = await sdk.getE3Stage(e3Id: bigint);
|
|
|
331
365
|
const reason = await sdk.getFailureReason(e3Id: bigint);
|
|
332
366
|
```
|
|
333
367
|
|
|
334
|
-
The original requester can cancel
|
|
335
|
-
|
|
336
|
-
|
|
368
|
+
The original requester can cancel only while the E3 is `Requested`, after the randomness deadline,
|
|
369
|
+
and only if no timely VRF result is usable. A valid result disables cancellation. The failure path
|
|
370
|
+
returns all service fee escrow and keeps the flat randomness fee charged.
|
|
337
371
|
|
|
338
372
|
```ts
|
|
339
373
|
const hash = await sdk.cancelE3(e3Id)
|
|
@@ -434,13 +468,35 @@ interface SDKConfig {
|
|
|
434
468
|
`thresholdBfvParamsPresetName` selects the BFV parameter set used for encryption. It must match the
|
|
435
469
|
on-chain `paramSet` index registered in the Interfold contract:
|
|
436
470
|
|
|
437
|
-
| Preset name | On-chain `paramSet` index | Use case
|
|
438
|
-
| -------------------------- | ------------------------- |
|
|
439
|
-
| `'INSECURE_THRESHOLD_512'` | `0` | Local development and
|
|
440
|
-
| `'SECURE_THRESHOLD_8192'` | `1` | Production — full security parameters (N=8192, L=
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
471
|
+
| Preset name | On-chain `paramSet` index | Use case |
|
|
472
|
+
| -------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
473
|
+
| `'INSECURE_THRESHOLD_512'` | `0` | Local development and Sepolia — small polynomial degree (N=512), fast but not cryptographically secure |
|
|
474
|
+
| `'SECURE_THRESHOLD_8192'` | `1` | Production — full security parameters (N=8192, L=3 CRT moduli) |
|
|
475
|
+
|
|
476
|
+
| Network | Preset | `paramSet` |
|
|
477
|
+
| ---------------------- | -------------------------- | ---------- |
|
|
478
|
+
| Local development | `'INSECURE_THRESHOLD_512'` | `0` |
|
|
479
|
+
| Sepolia testnet | `'INSECURE_THRESHOLD_512'` | `0` |
|
|
480
|
+
| Mainnet and production | `'SECURE_THRESHOLD_8192'` | `1` |
|
|
481
|
+
|
|
482
|
+
Use `'INSECURE_THRESHOLD_512'` on Sepolia: the Sepolia ciphernodes run the insecure preset, and the
|
|
483
|
+
circuit artifacts bundled in this package are compiled for it. Use `'SECURE_THRESHOLD_8192'` in
|
|
484
|
+
production, together with your own `secure-8192` circuit artifacts (see
|
|
485
|
+
[Proving](#proving-embedded-circuits-or-your-own)).
|
|
486
|
+
|
|
487
|
+
### Proving: embedded circuits or your own
|
|
488
|
+
|
|
489
|
+
`generateProof()`, `encryptNumberAndGenProof()`, and `encryptVectorAndGenProof()` run the
|
|
490
|
+
user-data-encryption (UDE) circuits bundled in this package. Those artifacts are compiled with
|
|
491
|
+
`--preset insecure-512 --committee minimum` (`scripts/compile-circuits.sh`), so they only match
|
|
492
|
+
`'INSECURE_THRESHOLD_512'` and a minimum-size committee. With `'SECURE_THRESHOLD_8192'`,
|
|
493
|
+
`encryptNumberAndGenInputs()` returns N=8192 circuit inputs that the bundled N=512 circuits cannot
|
|
494
|
+
execute.
|
|
495
|
+
|
|
496
|
+
For on-chain Honk verification, compile your own UDE, app, and fold circuits for the preset and
|
|
497
|
+
committee your deployment uses, emit the Solidity verifier from them, and feed them the witness from
|
|
498
|
+
`encryptNumberAndGenInputs()`. `examples/CRISP` in the monorepo shows the full flow. Secure
|
|
499
|
+
artifacts may ship here in a later release.
|
|
444
500
|
|
|
445
501
|
## Error Handling
|
|
446
502
|
|
package/dist/events/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var events_exports = {};
|
|
|
22
22
|
__export(events_exports, {
|
|
23
23
|
EventListener: () => EventListener,
|
|
24
24
|
InterfoldEventType: () => InterfoldEventType,
|
|
25
|
+
RandomnessProviderEventType: () => RandomnessProviderEventType,
|
|
25
26
|
RegistryEventType: () => RegistryEventType
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(events_exports);
|
|
@@ -45,6 +46,8 @@ var InterfoldEventType = /* @__PURE__ */ ((InterfoldEventType2) => {
|
|
|
45
46
|
})(InterfoldEventType || {});
|
|
46
47
|
var RegistryEventType = /* @__PURE__ */ ((RegistryEventType2) => {
|
|
47
48
|
RegistryEventType2["COMMITTEE_REQUESTED"] = "CommitteeRequested";
|
|
49
|
+
RegistryEventType2["COMMITTEE_RANDOMNESS_REQUESTED"] = "CommitteeRandomnessRequested";
|
|
50
|
+
RegistryEventType2["RANDOMNESS_CIRCUIT_BREAKER_TRIPPED"] = "RandomnessCircuitBreakerTripped";
|
|
48
51
|
RegistryEventType2["COMMITTEE_PUBLISHED"] = "CommitteePublished";
|
|
49
52
|
RegistryEventType2["COMMITTEE_FINALIZED"] = "SortitionCommitteeFinalized";
|
|
50
53
|
RegistryEventType2["INTERFOLD_SET"] = "InterfoldSet";
|
|
@@ -52,6 +55,10 @@ var RegistryEventType = /* @__PURE__ */ ((RegistryEventType2) => {
|
|
|
52
55
|
RegistryEventType2["INITIALIZED"] = "Initialized";
|
|
53
56
|
return RegistryEventType2;
|
|
54
57
|
})(RegistryEventType || {});
|
|
58
|
+
var RandomnessProviderEventType = /* @__PURE__ */ ((RandomnessProviderEventType2) => {
|
|
59
|
+
RandomnessProviderEventType2["RANDOMNESS_FULFILLED"] = "RandomnessFulfilled";
|
|
60
|
+
return RandomnessProviderEventType2;
|
|
61
|
+
})(RandomnessProviderEventType || {});
|
|
55
62
|
|
|
56
63
|
// src/utils.ts
|
|
57
64
|
var import_viem = require("viem");
|
|
@@ -68,8 +75,13 @@ var sleep = (ms) => {
|
|
|
68
75
|
|
|
69
76
|
// src/events/event-listener.ts
|
|
70
77
|
var EventListener = class _EventListener {
|
|
78
|
+
static DEFAULT_HISTORICAL_BLOCK_RANGE = 10000n;
|
|
79
|
+
static MAX_REMEMBERED_LOGS = 1e4;
|
|
71
80
|
listeners = /* @__PURE__ */ new Map();
|
|
72
81
|
activeWatchers = /* @__PURE__ */ new Map();
|
|
82
|
+
watcherStartBlocks = /* @__PURE__ */ new Map();
|
|
83
|
+
randomnessProviderListeners = /* @__PURE__ */ new Map();
|
|
84
|
+
seenLiveLogs = /* @__PURE__ */ new Map();
|
|
73
85
|
isPolling = false;
|
|
74
86
|
lastBlockNumber = BigInt(0);
|
|
75
87
|
publicClient;
|
|
@@ -86,6 +98,8 @@ var EventListener = class _EventListener {
|
|
|
86
98
|
// runtime; those default to the Interfold contract.
|
|
87
99
|
static REGISTRY_ONLY_EVENTS = /* @__PURE__ */ new Set([
|
|
88
100
|
"CommitteeRequested" /* COMMITTEE_REQUESTED */,
|
|
101
|
+
"CommitteeRandomnessRequested" /* COMMITTEE_RANDOMNESS_REQUESTED */,
|
|
102
|
+
"RandomnessCircuitBreakerTripped" /* RANDOMNESS_CIRCUIT_BREAKER_TRIPPED */,
|
|
89
103
|
"CommitteePublished" /* COMMITTEE_PUBLISHED */,
|
|
90
104
|
"SortitionCommitteeFinalized" /* COMMITTEE_FINALIZED */,
|
|
91
105
|
"InterfoldSet" /* INTERFOLD_SET */
|
|
@@ -101,6 +115,93 @@ var EventListener = class _EventListener {
|
|
|
101
115
|
const { address, abi } = this.resolveContract(eventType);
|
|
102
116
|
return this.watchContractEvent(address, eventType, abi, callback);
|
|
103
117
|
}
|
|
118
|
+
async onRandomnessProviderEvent(provider, eventType, callback, fromBlock) {
|
|
119
|
+
const listenerKey = `${provider.toLowerCase()}:${eventType}`;
|
|
120
|
+
const watcherKey = `randomness-provider:${listenerKey}`;
|
|
121
|
+
const requestedStartBlock = fromBlock ?? this.config.fromBlock;
|
|
122
|
+
let callbacks = this.randomnessProviderListeners.get(listenerKey);
|
|
123
|
+
if (!callbacks) {
|
|
124
|
+
callbacks = /* @__PURE__ */ new Set();
|
|
125
|
+
this.randomnessProviderListeners.set(listenerKey, callbacks);
|
|
126
|
+
}
|
|
127
|
+
if (this.activeWatchers.has(watcherKey)) {
|
|
128
|
+
const activeStartBlock = this.watcherStartBlocks.get(watcherKey);
|
|
129
|
+
if (fromBlock !== void 0 && requestedStartBlock !== activeStartBlock) {
|
|
130
|
+
throw new SDKError(
|
|
131
|
+
`Randomness provider watcher for ${eventType} on ${provider} already starts at ${activeStartBlock ?? "latest"}; requested ${requestedStartBlock ?? "latest"}`,
|
|
132
|
+
"INVALID_EVENT_CONFIG"
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
callbacks.add(callback);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
callbacks.add(callback);
|
|
139
|
+
try {
|
|
140
|
+
const unwatch = this.publicClient.watchContractEvent({
|
|
141
|
+
address: provider,
|
|
142
|
+
abi: import_types.IRandomnessProvider__factory.abi,
|
|
143
|
+
eventName: eventType,
|
|
144
|
+
fromBlock: requestedStartBlock,
|
|
145
|
+
onLogs: (logs) => {
|
|
146
|
+
for (const log of logs) {
|
|
147
|
+
if (!this.rememberLiveLog(log)) continue;
|
|
148
|
+
const event = {
|
|
149
|
+
type: eventType,
|
|
150
|
+
data: log.args,
|
|
151
|
+
provider,
|
|
152
|
+
log,
|
|
153
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
154
|
+
blockNumber: log.blockNumber ?? 0n,
|
|
155
|
+
transactionHash: log.transactionHash ?? "0x"
|
|
156
|
+
};
|
|
157
|
+
const currentCallbacks = this.randomnessProviderListeners.get(listenerKey);
|
|
158
|
+
currentCallbacks?.forEach((currentCallback) => {
|
|
159
|
+
try {
|
|
160
|
+
const result = currentCallback(event);
|
|
161
|
+
if (result) {
|
|
162
|
+
void result.catch((error) => {
|
|
163
|
+
console.error(`Error in randomness provider callback for ${eventType}:`, error);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error(`Error in randomness provider callback for ${eventType}:`, error);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
this.activeWatchers.set(watcherKey, unwatch);
|
|
174
|
+
this.watcherStartBlocks.set(watcherKey, requestedStartBlock);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
callbacks.delete(callback);
|
|
177
|
+
if (callbacks.size === 0) this.randomnessProviderListeners.delete(listenerKey);
|
|
178
|
+
throw new SDKError(`Failed to watch randomness provider event ${eventType} on ${provider}: ${error}`, "WATCH_EVENT_FAILED");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
offRandomnessProviderEvent(provider, eventType, callback) {
|
|
182
|
+
const listenerKey = `${provider.toLowerCase()}:${eventType}`;
|
|
183
|
+
const callbacks = this.randomnessProviderListeners.get(listenerKey);
|
|
184
|
+
callbacks?.delete(callback);
|
|
185
|
+
if (callbacks && callbacks.size === 0) {
|
|
186
|
+
this.randomnessProviderListeners.delete(listenerKey);
|
|
187
|
+
const watcherKey = `randomness-provider:${listenerKey}`;
|
|
188
|
+
const unwatch = this.activeWatchers.get(watcherKey);
|
|
189
|
+
if (unwatch) unwatch();
|
|
190
|
+
this.activeWatchers.delete(watcherKey);
|
|
191
|
+
this.watcherStartBlocks.delete(watcherKey);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async getHistoricalRandomnessProviderEvents(provider, eventType, fromBlock, toBlock) {
|
|
195
|
+
const start = fromBlock ?? this.config.fromBlock;
|
|
196
|
+
if (start === void 0) {
|
|
197
|
+
throw new SDKError("Randomness provider history requires fromBlock or EventListenerConfig.fromBlock", "INVALID_EVENT_CONFIG");
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
return await this.getHistoricalContractEvents(provider, import_types.IRandomnessProvider__factory.abi, eventType, start, toBlock);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
throw new SDKError(`Failed to get randomness provider events from ${provider}: ${error}`, "HISTORICAL_EVENTS_FAILED");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
104
205
|
async once(type, callback) {
|
|
105
206
|
const handler = (event) => {
|
|
106
207
|
this.off(type, handler);
|
|
@@ -129,6 +230,7 @@ var EventListener = class _EventListener {
|
|
|
129
230
|
for (let i = 0; i < logs.length; i++) {
|
|
130
231
|
const log = logs[i];
|
|
131
232
|
if (!log) break;
|
|
233
|
+
if (!emitter.rememberLiveLog(log)) continue;
|
|
132
234
|
const event = {
|
|
133
235
|
type: eventType,
|
|
134
236
|
data: log.args,
|
|
@@ -182,13 +284,7 @@ var EventListener = class _EventListener {
|
|
|
182
284
|
async getHistoricalEvents(eventType, fromBlock, toBlock) {
|
|
183
285
|
const { address, abi } = this.resolveContract(eventType);
|
|
184
286
|
try {
|
|
185
|
-
return await this.
|
|
186
|
-
address,
|
|
187
|
-
abi,
|
|
188
|
-
eventName: eventType,
|
|
189
|
-
fromBlock: fromBlock ?? this.config.fromBlock,
|
|
190
|
-
toBlock: toBlock ?? this.config.toBlock
|
|
191
|
-
});
|
|
287
|
+
return await this.getHistoricalContractEvents(address, abi, eventType, fromBlock, toBlock);
|
|
192
288
|
} catch (error) {
|
|
193
289
|
throw new SDKError(`Failed to get historical events: ${error}`, "HISTORICAL_EVENTS_FAILED");
|
|
194
290
|
}
|
|
@@ -247,7 +343,65 @@ var EventListener = class _EventListener {
|
|
|
247
343
|
}
|
|
248
344
|
});
|
|
249
345
|
this.activeWatchers.clear();
|
|
346
|
+
this.watcherStartBlocks.clear();
|
|
250
347
|
this.listeners.clear();
|
|
348
|
+
this.randomnessProviderListeners.clear();
|
|
349
|
+
this.seenLiveLogs.clear();
|
|
350
|
+
}
|
|
351
|
+
logIdentity(log) {
|
|
352
|
+
if (log.blockHash && log.transactionHash && log.logIndex !== null && log.logIndex !== void 0) {
|
|
353
|
+
return `${log.blockHash}:${log.transactionHash}:${log.logIndex}:${Boolean(log.removed)}`;
|
|
354
|
+
}
|
|
355
|
+
return void 0;
|
|
356
|
+
}
|
|
357
|
+
rememberLiveLog(log) {
|
|
358
|
+
const identity = this.logIdentity(log);
|
|
359
|
+
if (!identity) return true;
|
|
360
|
+
if (this.seenLiveLogs.has(identity)) return false;
|
|
361
|
+
this.seenLiveLogs.set(identity, true);
|
|
362
|
+
if (this.seenLiveLogs.size > _EventListener.MAX_REMEMBERED_LOGS) {
|
|
363
|
+
const oldest = this.seenLiveLogs.keys().next().value;
|
|
364
|
+
if (oldest !== void 0) this.seenLiveLogs.delete(oldest);
|
|
365
|
+
}
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
async getHistoricalContractEvents(address, abi, eventName, fromBlock, toBlock) {
|
|
369
|
+
const start = fromBlock ?? this.config.fromBlock;
|
|
370
|
+
const configuredEnd = toBlock ?? this.config.toBlock;
|
|
371
|
+
if (start === void 0) {
|
|
372
|
+
return await this.publicClient.getContractEvents({
|
|
373
|
+
address,
|
|
374
|
+
abi,
|
|
375
|
+
eventName,
|
|
376
|
+
toBlock: configuredEnd
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
const end = configuredEnd ?? await this.publicClient.getBlockNumber({ cacheTime: 0 });
|
|
380
|
+
if (end < start) return [];
|
|
381
|
+
const range = this.config.historicalBlockRange ?? _EventListener.DEFAULT_HISTORICAL_BLOCK_RANGE;
|
|
382
|
+
if (range <= 0n) throw new SDKError("Historical block range must be greater than zero", "INVALID_EVENT_CONFIG");
|
|
383
|
+
const logs = [];
|
|
384
|
+
const seen = /* @__PURE__ */ new Set();
|
|
385
|
+
for (let cursor = start; cursor <= end; cursor += range) {
|
|
386
|
+
const chunkEnd = cursor + range - 1n < end ? cursor + range - 1n : end;
|
|
387
|
+
const chunk = await this.publicClient.getContractEvents({
|
|
388
|
+
address,
|
|
389
|
+
abi,
|
|
390
|
+
eventName,
|
|
391
|
+
fromBlock: cursor,
|
|
392
|
+
toBlock: chunkEnd
|
|
393
|
+
});
|
|
394
|
+
for (const log of chunk) {
|
|
395
|
+
const identity = this.logIdentity(log);
|
|
396
|
+
if (identity && seen.has(identity)) continue;
|
|
397
|
+
if (identity) {
|
|
398
|
+
seen.add(identity);
|
|
399
|
+
this.rememberLiveLog(log);
|
|
400
|
+
}
|
|
401
|
+
logs.push(log);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return logs;
|
|
251
405
|
}
|
|
252
406
|
async pollForEvents() {
|
|
253
407
|
while (this.isPolling) {
|
|
@@ -268,6 +422,7 @@ var EventListener = class _EventListener {
|
|
|
268
422
|
0 && (module.exports = {
|
|
269
423
|
EventListener,
|
|
270
424
|
InterfoldEventType,
|
|
425
|
+
RandomnessProviderEventType,
|
|
271
426
|
RegistryEventType
|
|
272
427
|
});
|
|
273
428
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/events/index.ts","../../src/events/event-listener.ts","../../src/events/types.ts","../../src/utils.ts"],"sourcesContent":["// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nexport { EventListener } from './event-listener'\nexport type { EventListenerOptions } from './event-listener'\n\nexport { InterfoldEventType, RegistryEventType } from './types'\n\nexport type {\n AllEventTypes,\n InterfoldEvent,\n EventCallback,\n EventFilter,\n SDKEventEmitter,\n EventListenerConfig,\n E3RequestedData,\n E3ActivatedData,\n CiphertextOutputPublishedData,\n PlaintextOutputPublishedData,\n CiphernodeAddedData,\n CiphernodeRemovedData,\n CommitteeRequestedData,\n CommitteePublishedData,\n CommitteeFinalizedData,\n InterfoldEventData,\n RegistryEventData,\n} from './types'\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { type Abi, type Log, type PublicClient } from 'viem'\nimport { CiphernodeRegistryOwnable__factory, Interfold__factory } from '@interfold/contracts/types'\n\nimport {\n RegistryEventType,\n type AllEventTypes,\n type InterfoldEvent,\n type InterfoldEventData,\n type InterfoldEventType as InterfoldEventTypeT,\n type EventCallback,\n type EventListenerConfig,\n type RegistryEventData,\n type RegistryEventType as RegistryEventTypeT,\n type SDKEventEmitter,\n} from './types'\nimport type { ContractAddresses } from '../contracts/types'\nimport { SDKError, sleep } from '../utils'\n\nexport interface EventListenerOptions {\n publicClient: PublicClient\n contracts: ContractAddresses\n config?: EventListenerConfig\n}\n\nexport class EventListener implements SDKEventEmitter {\n private listeners: Map<AllEventTypes, Set<EventCallback>> = new Map()\n private activeWatchers: Map<string, () => void> = new Map()\n private isPolling = false\n private lastBlockNumber: bigint = BigInt(0)\n private publicClient: PublicClient\n private contracts: ContractAddresses\n private config: EventListenerConfig\n\n constructor(options: EventListenerOptions) {\n this.publicClient = options.publicClient\n this.contracts = options.contracts\n this.config = options.config || {}\n }\n\n // Registry-exclusive event names that don't collide with InterfoldEventType.\n // Shared names like 'OwnershipTransferred' and 'Initialized' exist in both\n // enums with the same string value, so they cannot be disambiguated at\n // runtime; those default to the Interfold contract.\n private static readonly REGISTRY_ONLY_EVENTS: ReadonlySet<string> = new Set([\n RegistryEventType.COMMITTEE_REQUESTED,\n RegistryEventType.COMMITTEE_PUBLISHED,\n RegistryEventType.COMMITTEE_FINALIZED,\n RegistryEventType.INTERFOLD_SET,\n ])\n\n private resolveContract(eventType: AllEventTypes): { address: `0x${string}`; abi: Abi } {\n const isRegistryEvent = EventListener.REGISTRY_ONLY_EVENTS.has(eventType as string)\n return {\n address: isRegistryEvent ? this.contracts.ciphernodeRegistry : this.contracts.interfold,\n abi: isRegistryEvent ? CiphernodeRegistryOwnable__factory.abi : Interfold__factory.abi,\n }\n }\n\n public async onInterfoldEvent<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): Promise<void> {\n const { address, abi } = this.resolveContract(eventType)\n return this.watchContractEvent(address, eventType, abi, callback)\n }\n\n public async once<T extends AllEventTypes>(type: T, callback: EventCallback<T>): Promise<void> {\n const handler: EventCallback<T> = (event) => {\n this.off(type, handler)\n const prom = callback(event)\n if (prom) {\n prom.catch((e) => console.error(e))\n }\n }\n return this.onInterfoldEvent(type, handler)\n }\n\n public async watchContractEvent<T extends AllEventTypes>(\n address: `0x${string}`,\n eventType: T,\n abi: Abi,\n callback: EventCallback<T>,\n ): Promise<void> {\n const watcherKey = `${address}:${eventType}`\n\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set())\n }\n this.listeners.get(eventType)!.add(callback as EventCallback)\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const emitter = this\n\n if (!this.activeWatchers.has(watcherKey)) {\n try {\n const unwatch = this.publicClient.watchContractEvent({\n address,\n abi,\n eventName: eventType as string,\n fromBlock: this.config.fromBlock,\n onLogs(logs: Log[]) {\n for (let i = 0; i < logs.length; i++) {\n const log = logs[i]\n if (!log) break\n const event: InterfoldEvent<T> = {\n type: eventType,\n data: (log as unknown as { args: unknown }).args as T extends InterfoldEventTypeT\n ? InterfoldEventData[T]\n : T extends RegistryEventTypeT\n ? RegistryEventData[T]\n : unknown,\n log,\n timestamp: new Date(),\n blockNumber: log.blockNumber ?? BigInt(0),\n transactionHash: log.transactionHash ?? '0x',\n }\n emitter.emit(event)\n }\n },\n })\n\n this.activeWatchers.set(watcherKey, unwatch)\n } catch (error) {\n throw new SDKError(`Failed to watch contract event ${eventType} on ${address}: ${error}`, 'WATCH_EVENT_FAILED')\n }\n }\n }\n\n public async watchLogs(address: `0x${string}`, callback: (log: Log) => void): Promise<void> {\n const watcherKey = `logs:${address}`\n\n if (!this.activeWatchers.has(watcherKey)) {\n try {\n const unwatch = this.publicClient.watchEvent({\n address,\n onLogs: (logs: Log[]) => {\n logs.forEach((log: Log) => {\n callback(log)\n })\n },\n })\n\n this.activeWatchers.set(watcherKey, unwatch)\n } catch (error) {\n throw new SDKError(`Failed to watch logs for address ${address}: ${error}`, 'WATCH_LOGS_FAILED')\n }\n }\n }\n\n public async startPolling(): Promise<void> {\n if (this.isPolling) return\n\n this.isPolling = true\n\n try {\n this.lastBlockNumber = await this.publicClient.getBlockNumber()\n void this.pollForEvents()\n } catch (error) {\n this.isPolling = false\n throw new SDKError(`Failed to start polling: ${error}`, 'POLLING_START_FAILED')\n }\n }\n\n public stopPolling(): void {\n this.isPolling = false\n }\n\n public async getHistoricalEvents(eventType: AllEventTypes, fromBlock?: bigint, toBlock?: bigint): Promise<Log[]> {\n const { address, abi } = this.resolveContract(eventType)\n\n try {\n return await this.publicClient.getContractEvents({\n address,\n abi,\n eventName: eventType as string,\n fromBlock: fromBlock ?? this.config.fromBlock,\n toBlock: toBlock ?? this.config.toBlock,\n })\n } catch (error) {\n throw new SDKError(`Failed to get historical events: ${error}`, 'HISTORICAL_EVENTS_FAILED')\n }\n }\n\n public on<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): void {\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set())\n }\n this.listeners.get(eventType)!.add(callback as EventCallback)\n }\n\n public off<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): void {\n const callbacks = this.listeners.get(eventType)\n if (callbacks) {\n callbacks.delete(callback as EventCallback)\n if (callbacks.size === 0) {\n this.listeners.delete(eventType)\n const watchersToRemove: string[] = []\n this.activeWatchers.forEach((unwatch, key) => {\n if (key.endsWith(`:${eventType}`)) {\n try {\n unwatch()\n } catch (error) {\n console.error(`Error unwatching event ${eventType}:`, error)\n }\n watchersToRemove.push(key)\n }\n })\n watchersToRemove.forEach((key) => this.activeWatchers.delete(key))\n }\n }\n }\n\n public emit<T extends AllEventTypes>(event: InterfoldEvent<T>): void {\n const callbacks = this.listeners.get(event.type)\n if (callbacks) {\n callbacks.forEach((callback) => {\n try {\n const result = (callback as EventCallback<T>)(event)\n if (result) {\n void result.catch((error) => {\n console.error(`Error in event callback for ${event.type}:`, error)\n })\n }\n } catch (error) {\n console.error(`Error in event callback for ${event.type}:`, error)\n }\n })\n }\n }\n\n public cleanup(): void {\n this.stopPolling()\n\n this.activeWatchers.forEach((unwatch) => {\n try {\n unwatch()\n } catch (error) {\n console.error('Error unwatching during cleanup:', error)\n }\n })\n this.activeWatchers.clear()\n this.listeners.clear()\n }\n\n private async pollForEvents(): Promise<void> {\n while (this.isPolling) {\n try {\n const currentBlock = await this.publicClient.getBlockNumber()\n\n if (currentBlock > this.lastBlockNumber) {\n this.lastBlockNumber = currentBlock\n }\n\n await sleep(this.config.pollingInterval || 5000)\n } catch (error) {\n console.error('Error during polling:', error)\n await sleep(this.config.pollingInterval || 5000)\n }\n }\n }\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport type { Log } from 'viem'\n\nexport enum InterfoldEventType {\n E3_REQUESTED = 'E3Requested',\n CIPHERTEXT_OUTPUT_PUBLISHED = 'CiphertextOutputPublished',\n PLAINTEXT_OUTPUT_PUBLISHED = 'PlaintextOutputPublished',\n E3_PROGRAM_REGISTERED = 'E3ProgramRegistered',\n ENCRYPTION_SCHEME_ENABLED = 'EncryptionSchemeEnabled',\n CIPHERNODE_REGISTRY_SET = 'CiphernodeRegistrySet',\n MAX_DURATION_SET = 'MaxDurationSet',\n PARAM_SET_REGISTERED = 'ParamSetRegistered',\n OWNERSHIP_TRANSFERRED = 'OwnershipTransferred',\n INITIALIZED = 'Initialized',\n}\n\nexport enum RegistryEventType {\n COMMITTEE_REQUESTED = 'CommitteeRequested',\n COMMITTEE_PUBLISHED = 'CommitteePublished',\n COMMITTEE_FINALIZED = 'SortitionCommitteeFinalized',\n INTERFOLD_SET = 'InterfoldSet',\n OWNERSHIP_TRANSFERRED = 'OwnershipTransferred',\n INITIALIZED = 'Initialized',\n}\n\nexport type AllEventTypes = InterfoldEventType | RegistryEventType\n\nexport interface E3RequestedData {\n e3Id: bigint\n e3: {\n seed: bigint\n committeeSize: number\n requestBlock: bigint\n inputWindow: readonly [bigint, bigint]\n encryptionSchemeId: string\n e3Program: string\n paramSet: number\n decryptionVerifier: string\n committeePublicKey: string\n ciphertextOutput: string\n ciphertextCommitment: string\n plaintextOutput: string\n }\n cryptoConfigId: string\n}\n\nexport interface E3ActivatedData {\n e3Id: bigint\n expiration: bigint\n committeePublicKey: string\n}\n\nexport interface CiphertextOutputPublishedData {\n e3Id: bigint\n ciphertextOutput: string\n ciphertextCommitment: string\n}\n\nexport interface PlaintextOutputPublishedData {\n e3Id: bigint\n plaintextOutput: string\n proof: string\n}\n\nexport interface CiphernodeAddedData {\n node: string\n index: bigint\n numNodes: bigint\n size: bigint\n}\n\nexport interface CiphernodeRemovedData {\n node: string\n index: bigint\n numNodes: bigint\n size: bigint\n}\n\nexport interface CommitteeRequestedData {\n e3Id: bigint\n entropyBlock: bigint\n threshold: [bigint, bigint]\n requestBlock: bigint\n committeeDeadline: bigint\n ticketPrice: bigint\n}\n\nexport interface CommitteePublishedData {\n e3Id: bigint\n nodes: string[]\n publicKey: string\n pkCommitment: string\n proof: string\n}\n\nexport interface CommitteeFinalizedData {\n e3Id: bigint\n committee: string[]\n scores: bigint[]\n}\n\nexport interface InterfoldEventData {\n [InterfoldEventType.E3_REQUESTED]: E3RequestedData\n [InterfoldEventType.CIPHERTEXT_OUTPUT_PUBLISHED]: CiphertextOutputPublishedData\n [InterfoldEventType.PLAINTEXT_OUTPUT_PUBLISHED]: PlaintextOutputPublishedData\n [InterfoldEventType.E3_PROGRAM_REGISTERED]: { e3Program: string }\n [InterfoldEventType.ENCRYPTION_SCHEME_ENABLED]: { encryptionSchemeId: string }\n [InterfoldEventType.CIPHERNODE_REGISTRY_SET]: { ciphernodeRegistry: string }\n [InterfoldEventType.MAX_DURATION_SET]: { maxDuration: bigint }\n [InterfoldEventType.PARAM_SET_REGISTERED]: { paramSet: number; encodedParams: string }\n [InterfoldEventType.OWNERSHIP_TRANSFERRED]: { previousOwner: string; newOwner: string }\n [InterfoldEventType.INITIALIZED]: { version: bigint }\n}\n\nexport interface RegistryEventData {\n [RegistryEventType.COMMITTEE_REQUESTED]: CommitteeRequestedData\n [RegistryEventType.COMMITTEE_PUBLISHED]: CommitteePublishedData\n [RegistryEventType.COMMITTEE_FINALIZED]: CommitteeFinalizedData\n [RegistryEventType.INTERFOLD_SET]: { interfold: string }\n [RegistryEventType.OWNERSHIP_TRANSFERRED]: { previousOwner: string; newOwner: string }\n [RegistryEventType.INITIALIZED]: { version: bigint }\n}\n\nexport interface InterfoldEvent<T extends AllEventTypes> {\n type: T\n data: T extends InterfoldEventType ? InterfoldEventData[T] : T extends RegistryEventType ? RegistryEventData[T] : unknown\n log: Log\n timestamp: Date\n blockNumber: bigint\n transactionHash: string\n}\n\nexport type EventCallback<T extends AllEventTypes = AllEventTypes> = (event: InterfoldEvent<T>) => void | Promise<void>\n\nexport interface EventFilter<T = unknown> {\n address?: `0x${string}`\n fromBlock?: bigint\n toBlock?: bigint\n args?: Partial<T>\n}\n\nexport interface SDKEventEmitter {\n on<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): void\n off<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): void\n emit<T extends AllEventTypes>(event: InterfoldEvent<T>): void\n}\n\nexport interface EventListenerConfig {\n fromBlock?: bigint\n toBlock?: bigint\n polling?: boolean\n pollingInterval?: number\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { type Address, type Hash, type Log, PublicClient, encodeAbiParameters } from 'viem'\nimport type { BfvParams } from './types'\n\nexport class SDKError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n }\n}\n\nexport function isValidAddress(address: string): address is Address {\n return /^0x[a-fA-F0-9]{40}$/.test(address)\n}\n\nexport function isValidHash(hash: string): hash is Hash {\n return /^0x[a-fA-F0-9]{64}$/.test(hash)\n}\n\nexport function formatEventName(contractName: string, eventName: string): string {\n return `${contractName}.${eventName}`\n}\n\nexport function parseEventData<T>(log: Log): T {\n return log.data as unknown as T\n}\n\n/**\n * Sleep for a specified number of milliseconds\n */\nexport const sleep = (ms: number): Promise<void> => {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function formatBigInt(value: bigint): string {\n return value.toString()\n}\n\nexport function parseBigInt(value: string): bigint {\n return BigInt(value)\n}\n\nexport function generateEventId(log: Log): string {\n return `${log.blockHash}-${log.logIndex}`\n}\n\n/**\n * Get the current timestamp in seconds\n * from onchain\n * @param publicClient - The public client to use\n */\nexport async function getCurrentTimestamp(publicClient: PublicClient): Promise<bigint> {\n const block = await publicClient.getBlock()\n return block.timestamp\n}\n\n// Compute provider parameters structure\nexport interface ComputeProviderParams {\n name: string\n parallel: boolean\n batch_size: number\n}\n\n// Default compute provider configuration\nexport const DEFAULT_COMPUTE_PROVIDER_PARAMS: ComputeProviderParams = {\n name: 'risc0',\n parallel: false,\n batch_size: 2,\n}\n\n// Default E3 configuration (`committeeSize` is `IInterfold.CommitteeSize`, not circuit N_PARTIES).\nexport const DEFAULT_E3_CONFIG = {\n committeeSize: 0, // CommitteeSize.Minimum\n duration: 1800, // 30 minutes in seconds\n payment_amount: '0', // 0 ETH in wei\n} as const\n\n/**\n * Encode BFV parameters for the smart contract\n * BFV (Brakerski-Fan-Vercauteren) is a type of fully homomorphic encryption\n */\nexport function encodeBfvParams(params: BfvParams): `0x${string}` {\n const { degree, plaintextModulus, moduli, error1Variance } = params\n\n if (error1Variance === undefined) {\n throw new SDKError(\n 'error1Variance is required in ProtocolParams. All BFV parameter sets must specify error1_variance.',\n 'MISSING_ERROR1_VARIANCE',\n )\n }\n\n return encodeAbiParameters(\n [\n {\n name: 'bfvParams',\n type: 'tuple',\n components: [\n { name: 'degree', type: 'uint256' },\n { name: 'plaintext_modulus', type: 'uint256' },\n { name: 'moduli', type: 'uint256[]' },\n { name: 'error1_variance', type: 'string' },\n ],\n },\n ],\n [\n {\n degree: BigInt(degree),\n plaintext_modulus: BigInt(plaintextModulus),\n moduli: [...moduli],\n error1_variance: error1Variance,\n },\n ],\n )\n}\n\n/**\n * Encode compute provider parameters for the smart contract'\n * If mock is true, the compute provider parameters will return 32 bytes of 0x00\n */\nexport function encodeComputeProviderParams(params: ComputeProviderParams, mock: boolean = false): `0x${string}` {\n if (mock) {\n return `0x${'00'.repeat(32)}` as `0x${string}`\n }\n\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n/**\n * Encode custom parameters for the smart contract.\n */\nexport function encodeCustomParams(params: Record<string, unknown>): `0x${string}` {\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n// inputWindow[0] is always larger than now and dkg deadline\nexport const inputWindowStartBuffer = 15n\n\n/**\n * Calculate start window for E3 request\n * @dev This function can be used for testing purposes, or for E3s which need to start as soon as possible.\n * @param publicClient - The public client to use\n * @param duration - The duration of the input window in seconds\n * @param startBuffer - Buffer in seconds added to current timestamp for input window start\n */\nexport async function calculateInputWindow(\n publicClient: PublicClient,\n duration: number = DEFAULT_E3_CONFIG.duration,\n startBuffer: bigint = inputWindowStartBuffer,\n): Promise<[bigint, bigint]> {\n const now = await getCurrentTimestamp(publicClient)\n return [BigInt(now) + startBuffer, BigInt(now) + startBuffer + BigInt(duration)]\n}\n\n/**\n * Decode plaintextOutput bytes to get the actual result number\n */\nexport function decodePlaintextOutput(plaintextOutput: string): number | null {\n try {\n // Remove '0x' prefix if present\n const hex = plaintextOutput.startsWith('0x') ? plaintextOutput.slice(2) : plaintextOutput\n\n // Convert hex to bytes\n const bytes = new Uint8Array(hex.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) || [])\n\n if (bytes.length < 8) {\n console.warn('Plaintext output too short for u64 decoding')\n return null\n }\n\n // Decode first u64 (8 bytes) as little-endian\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n const result = view.getBigUint64(0, true) // true for little-endian\n\n return Number(result)\n } catch (error) {\n console.error('Failed to decode plaintext output:', error)\n return null\n }\n}\n\n// Helper function to convert proof bytes to field elements\nexport function proofToFields(proof: Uint8Array): string[] {\n const fields: string[] = []\n for (let i = 0; i < proof.length; i += 32) {\n const chunk = proof.slice(i, i + 32)\n fields.push('0x' + Buffer.from(chunk).toString('hex'))\n }\n return fields\n}\n"],"mappings":"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","names":["InterfoldEventType","RegistryEventType"]}
|
|
1
|
+
{"version":3,"sources":["../../src/events/index.ts","../../src/events/event-listener.ts","../../src/events/types.ts","../../src/utils.ts"],"sourcesContent":["// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nexport { EventListener } from './event-listener'\nexport type { EventListenerOptions } from './event-listener'\n\nexport { InterfoldEventType, RandomnessProviderEventType, RegistryEventType } from './types'\n\nexport type {\n AllEventTypes,\n InterfoldEvent,\n EventCallback,\n EventFilter,\n SDKEventEmitter,\n EventListenerConfig,\n E3RequestedData,\n E3ActivatedData,\n CiphertextOutputPublishedData,\n PlaintextOutputPublishedData,\n CiphernodeAddedData,\n CiphernodeRemovedData,\n CommitteeRequestedData,\n CommitteeRandomnessRequestedData,\n RandomnessCircuitBreakerTrippedData,\n RandomnessFulfilledData,\n RandomnessProviderEvent,\n RandomnessProviderEventCallback,\n CommitteePublishedData,\n CommitteeFinalizedData,\n InterfoldEventData,\n RegistryEventData,\n} from './types'\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { type Abi, type Log, type PublicClient } from 'viem'\nimport { CiphernodeRegistryOwnable__factory, Interfold__factory, IRandomnessProvider__factory } from '@interfold/contracts/types'\n\nimport {\n RegistryEventType,\n type RandomnessProviderEvent,\n type RandomnessProviderEventCallback,\n type RandomnessProviderEventType,\n type AllEventTypes,\n type InterfoldEvent,\n type InterfoldEventData,\n type InterfoldEventType as InterfoldEventTypeT,\n type EventCallback,\n type EventListenerConfig,\n type RegistryEventData,\n type RegistryEventType as RegistryEventTypeT,\n type SDKEventEmitter,\n} from './types'\nimport type { ContractAddresses } from '../contracts/types'\nimport { SDKError, sleep } from '../utils'\n\nexport interface EventListenerOptions {\n publicClient: PublicClient\n contracts: ContractAddresses\n config?: EventListenerConfig\n}\n\nexport class EventListener implements SDKEventEmitter {\n private static readonly DEFAULT_HISTORICAL_BLOCK_RANGE = 10_000n\n private static readonly MAX_REMEMBERED_LOGS = 10_000\n private listeners: Map<AllEventTypes, Set<EventCallback>> = new Map()\n private activeWatchers: Map<string, () => void> = new Map()\n private watcherStartBlocks: Map<string, bigint | undefined> = new Map()\n private randomnessProviderListeners: Map<string, Set<RandomnessProviderEventCallback>> = new Map()\n private seenLiveLogs: Map<string, true> = new Map()\n private isPolling = false\n private lastBlockNumber: bigint = BigInt(0)\n private publicClient: PublicClient\n private contracts: ContractAddresses\n private config: EventListenerConfig\n\n constructor(options: EventListenerOptions) {\n this.publicClient = options.publicClient\n this.contracts = options.contracts\n this.config = options.config || {}\n }\n\n // Registry-exclusive event names that don't collide with InterfoldEventType.\n // Shared names like 'OwnershipTransferred' and 'Initialized' exist in both\n // enums with the same string value, so they cannot be disambiguated at\n // runtime; those default to the Interfold contract.\n private static readonly REGISTRY_ONLY_EVENTS: ReadonlySet<string> = new Set([\n RegistryEventType.COMMITTEE_REQUESTED,\n RegistryEventType.COMMITTEE_RANDOMNESS_REQUESTED,\n RegistryEventType.RANDOMNESS_CIRCUIT_BREAKER_TRIPPED,\n RegistryEventType.COMMITTEE_PUBLISHED,\n RegistryEventType.COMMITTEE_FINALIZED,\n RegistryEventType.INTERFOLD_SET,\n ])\n\n private resolveContract(eventType: AllEventTypes): { address: `0x${string}`; abi: Abi } {\n const isRegistryEvent = EventListener.REGISTRY_ONLY_EVENTS.has(eventType as string)\n return {\n address: isRegistryEvent ? this.contracts.ciphernodeRegistry : this.contracts.interfold,\n abi: isRegistryEvent ? CiphernodeRegistryOwnable__factory.abi : Interfold__factory.abi,\n }\n }\n\n public async onInterfoldEvent<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): Promise<void> {\n const { address, abi } = this.resolveContract(eventType)\n return this.watchContractEvent(address, eventType, abi, callback)\n }\n\n public async onRandomnessProviderEvent<T extends RandomnessProviderEventType>(\n provider: `0x${string}`,\n eventType: T,\n callback: RandomnessProviderEventCallback<T>,\n fromBlock?: bigint,\n ): Promise<void> {\n const listenerKey = `${provider.toLowerCase()}:${eventType}`\n const watcherKey = `randomness-provider:${listenerKey}`\n const requestedStartBlock = fromBlock ?? this.config.fromBlock\n let callbacks = this.randomnessProviderListeners.get(listenerKey)\n if (!callbacks) {\n callbacks = new Set()\n this.randomnessProviderListeners.set(listenerKey, callbacks)\n }\n\n if (this.activeWatchers.has(watcherKey)) {\n const activeStartBlock = this.watcherStartBlocks.get(watcherKey)\n if (fromBlock !== undefined && requestedStartBlock !== activeStartBlock) {\n throw new SDKError(\n `Randomness provider watcher for ${eventType} on ${provider} already starts at ${activeStartBlock ?? 'latest'}; requested ${requestedStartBlock ?? 'latest'}`,\n 'INVALID_EVENT_CONFIG',\n )\n }\n callbacks.add(callback as RandomnessProviderEventCallback)\n return\n }\n\n callbacks.add(callback as RandomnessProviderEventCallback)\n\n try {\n const unwatch = this.publicClient.watchContractEvent({\n address: provider,\n abi: IRandomnessProvider__factory.abi,\n eventName: eventType,\n fromBlock: requestedStartBlock,\n onLogs: (logs: Log[]) => {\n for (const log of logs) {\n if (!this.rememberLiveLog(log)) continue\n const event: RandomnessProviderEvent<T> = {\n type: eventType,\n data: (log as unknown as { args: RandomnessProviderEvent<T>['data'] }).args,\n provider,\n log,\n timestamp: new Date(),\n blockNumber: log.blockNumber ?? 0n,\n transactionHash: log.transactionHash ?? '0x',\n }\n const currentCallbacks = this.randomnessProviderListeners.get(listenerKey)\n currentCallbacks?.forEach((currentCallback) => {\n try {\n const result = currentCallback(event)\n if (result) {\n void result.catch((error) => {\n console.error(`Error in randomness provider callback for ${eventType}:`, error)\n })\n }\n } catch (error) {\n console.error(`Error in randomness provider callback for ${eventType}:`, error)\n }\n })\n }\n },\n })\n this.activeWatchers.set(watcherKey, unwatch)\n this.watcherStartBlocks.set(watcherKey, requestedStartBlock)\n } catch (error) {\n callbacks.delete(callback as RandomnessProviderEventCallback)\n if (callbacks.size === 0) this.randomnessProviderListeners.delete(listenerKey)\n throw new SDKError(`Failed to watch randomness provider event ${eventType} on ${provider}: ${error}`, 'WATCH_EVENT_FAILED')\n }\n }\n\n public offRandomnessProviderEvent<T extends RandomnessProviderEventType>(\n provider: `0x${string}`,\n eventType: T,\n callback: RandomnessProviderEventCallback<T>,\n ): void {\n const listenerKey = `${provider.toLowerCase()}:${eventType}`\n const callbacks = this.randomnessProviderListeners.get(listenerKey)\n callbacks?.delete(callback as RandomnessProviderEventCallback)\n if (callbacks && callbacks.size === 0) {\n this.randomnessProviderListeners.delete(listenerKey)\n const watcherKey = `randomness-provider:${listenerKey}`\n const unwatch = this.activeWatchers.get(watcherKey)\n if (unwatch) unwatch()\n this.activeWatchers.delete(watcherKey)\n this.watcherStartBlocks.delete(watcherKey)\n }\n }\n\n public async getHistoricalRandomnessProviderEvents(\n provider: `0x${string}`,\n eventType: RandomnessProviderEventType,\n fromBlock?: bigint,\n toBlock?: bigint,\n ): Promise<Log[]> {\n const start = fromBlock ?? this.config.fromBlock\n if (start === undefined) {\n throw new SDKError('Randomness provider history requires fromBlock or EventListenerConfig.fromBlock', 'INVALID_EVENT_CONFIG')\n }\n try {\n return await this.getHistoricalContractEvents(provider, IRandomnessProvider__factory.abi, eventType, start, toBlock)\n } catch (error) {\n throw new SDKError(`Failed to get randomness provider events from ${provider}: ${error}`, 'HISTORICAL_EVENTS_FAILED')\n }\n }\n\n public async once<T extends AllEventTypes>(type: T, callback: EventCallback<T>): Promise<void> {\n const handler: EventCallback<T> = (event) => {\n this.off(type, handler)\n const prom = callback(event)\n if (prom) {\n prom.catch((e) => console.error(e))\n }\n }\n return this.onInterfoldEvent(type, handler)\n }\n\n public async watchContractEvent<T extends AllEventTypes>(\n address: `0x${string}`,\n eventType: T,\n abi: Abi,\n callback: EventCallback<T>,\n ): Promise<void> {\n const watcherKey = `${address}:${eventType}`\n\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set())\n }\n this.listeners.get(eventType)!.add(callback as EventCallback)\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const emitter = this\n\n if (!this.activeWatchers.has(watcherKey)) {\n try {\n const unwatch = this.publicClient.watchContractEvent({\n address,\n abi,\n eventName: eventType as string,\n fromBlock: this.config.fromBlock,\n onLogs(logs: Log[]) {\n for (let i = 0; i < logs.length; i++) {\n const log = logs[i]\n if (!log) break\n if (!emitter.rememberLiveLog(log)) continue\n const event: InterfoldEvent<T> = {\n type: eventType,\n data: (log as unknown as { args: unknown }).args as T extends InterfoldEventTypeT\n ? InterfoldEventData[T]\n : T extends RegistryEventTypeT\n ? RegistryEventData[T]\n : unknown,\n log,\n timestamp: new Date(),\n blockNumber: log.blockNumber ?? BigInt(0),\n transactionHash: log.transactionHash ?? '0x',\n }\n emitter.emit(event)\n }\n },\n })\n\n this.activeWatchers.set(watcherKey, unwatch)\n } catch (error) {\n throw new SDKError(`Failed to watch contract event ${eventType} on ${address}: ${error}`, 'WATCH_EVENT_FAILED')\n }\n }\n }\n\n public async watchLogs(address: `0x${string}`, callback: (log: Log) => void): Promise<void> {\n const watcherKey = `logs:${address}`\n\n if (!this.activeWatchers.has(watcherKey)) {\n try {\n const unwatch = this.publicClient.watchEvent({\n address,\n onLogs: (logs: Log[]) => {\n logs.forEach((log: Log) => {\n callback(log)\n })\n },\n })\n\n this.activeWatchers.set(watcherKey, unwatch)\n } catch (error) {\n throw new SDKError(`Failed to watch logs for address ${address}: ${error}`, 'WATCH_LOGS_FAILED')\n }\n }\n }\n\n public async startPolling(): Promise<void> {\n if (this.isPolling) return\n\n this.isPolling = true\n\n try {\n this.lastBlockNumber = await this.publicClient.getBlockNumber()\n void this.pollForEvents()\n } catch (error) {\n this.isPolling = false\n throw new SDKError(`Failed to start polling: ${error}`, 'POLLING_START_FAILED')\n }\n }\n\n public stopPolling(): void {\n this.isPolling = false\n }\n\n public async getHistoricalEvents(eventType: AllEventTypes, fromBlock?: bigint, toBlock?: bigint): Promise<Log[]> {\n const { address, abi } = this.resolveContract(eventType)\n\n try {\n return await this.getHistoricalContractEvents(address, abi, eventType as string, fromBlock, toBlock)\n } catch (error) {\n throw new SDKError(`Failed to get historical events: ${error}`, 'HISTORICAL_EVENTS_FAILED')\n }\n }\n\n public on<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): void {\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set())\n }\n this.listeners.get(eventType)!.add(callback as EventCallback)\n }\n\n public off<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): void {\n const callbacks = this.listeners.get(eventType)\n if (callbacks) {\n callbacks.delete(callback as EventCallback)\n if (callbacks.size === 0) {\n this.listeners.delete(eventType)\n const watchersToRemove: string[] = []\n this.activeWatchers.forEach((unwatch, key) => {\n if (key.endsWith(`:${eventType}`)) {\n try {\n unwatch()\n } catch (error) {\n console.error(`Error unwatching event ${eventType}:`, error)\n }\n watchersToRemove.push(key)\n }\n })\n watchersToRemove.forEach((key) => this.activeWatchers.delete(key))\n }\n }\n }\n\n public emit<T extends AllEventTypes>(event: InterfoldEvent<T>): void {\n const callbacks = this.listeners.get(event.type)\n if (callbacks) {\n callbacks.forEach((callback) => {\n try {\n const result = (callback as EventCallback<T>)(event)\n if (result) {\n void result.catch((error) => {\n console.error(`Error in event callback for ${event.type}:`, error)\n })\n }\n } catch (error) {\n console.error(`Error in event callback for ${event.type}:`, error)\n }\n })\n }\n }\n\n public cleanup(): void {\n this.stopPolling()\n\n this.activeWatchers.forEach((unwatch) => {\n try {\n unwatch()\n } catch (error) {\n console.error('Error unwatching during cleanup:', error)\n }\n })\n this.activeWatchers.clear()\n this.watcherStartBlocks.clear()\n this.listeners.clear()\n this.randomnessProviderListeners.clear()\n this.seenLiveLogs.clear()\n }\n\n private logIdentity(log: Log): string | undefined {\n if (log.blockHash && log.transactionHash && log.logIndex !== null && log.logIndex !== undefined) {\n return `${log.blockHash}:${log.transactionHash}:${log.logIndex}:${Boolean(log.removed)}`\n }\n return undefined\n }\n\n private rememberLiveLog(log: Log): boolean {\n const identity = this.logIdentity(log)\n if (!identity) return true\n if (this.seenLiveLogs.has(identity)) return false\n\n this.seenLiveLogs.set(identity, true)\n if (this.seenLiveLogs.size > EventListener.MAX_REMEMBERED_LOGS) {\n const oldest = this.seenLiveLogs.keys().next().value\n if (oldest !== undefined) this.seenLiveLogs.delete(oldest)\n }\n return true\n }\n\n private async getHistoricalContractEvents(\n address: `0x${string}`,\n abi: Abi,\n eventName: string,\n fromBlock?: bigint,\n toBlock?: bigint,\n ): Promise<Log[]> {\n const start = fromBlock ?? this.config.fromBlock\n const configuredEnd = toBlock ?? this.config.toBlock\n if (start === undefined) {\n return (await this.publicClient.getContractEvents({\n address,\n abi,\n eventName,\n toBlock: configuredEnd,\n })) as Log[]\n }\n\n const end = configuredEnd ?? (await this.publicClient.getBlockNumber({ cacheTime: 0 }))\n if (end < start) return []\n\n const range = this.config.historicalBlockRange ?? EventListener.DEFAULT_HISTORICAL_BLOCK_RANGE\n if (range <= 0n) throw new SDKError('Historical block range must be greater than zero', 'INVALID_EVENT_CONFIG')\n\n const logs: Log[] = []\n const seen = new Set<string>()\n for (let cursor = start; cursor <= end; cursor += range) {\n const chunkEnd = cursor + range - 1n < end ? cursor + range - 1n : end\n const chunk = (await this.publicClient.getContractEvents({\n address,\n abi,\n eventName,\n fromBlock: cursor,\n toBlock: chunkEnd,\n })) as Log[]\n for (const log of chunk) {\n const identity = this.logIdentity(log)\n if (identity && seen.has(identity)) continue\n if (identity) {\n seen.add(identity)\n this.rememberLiveLog(log)\n }\n logs.push(log)\n }\n }\n return logs\n }\n\n private async pollForEvents(): Promise<void> {\n while (this.isPolling) {\n try {\n const currentBlock = await this.publicClient.getBlockNumber()\n\n if (currentBlock > this.lastBlockNumber) {\n this.lastBlockNumber = currentBlock\n }\n\n await sleep(this.config.pollingInterval || 5000)\n } catch (error) {\n console.error('Error during polling:', error)\n await sleep(this.config.pollingInterval || 5000)\n }\n }\n }\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport type { Log } from 'viem'\n\nexport enum InterfoldEventType {\n E3_REQUESTED = 'E3Requested',\n CIPHERTEXT_OUTPUT_PUBLISHED = 'CiphertextOutputPublished',\n PLAINTEXT_OUTPUT_PUBLISHED = 'PlaintextOutputPublished',\n E3_PROGRAM_REGISTERED = 'E3ProgramRegistered',\n ENCRYPTION_SCHEME_ENABLED = 'EncryptionSchemeEnabled',\n CIPHERNODE_REGISTRY_SET = 'CiphernodeRegistrySet',\n MAX_DURATION_SET = 'MaxDurationSet',\n PARAM_SET_REGISTERED = 'ParamSetRegistered',\n OWNERSHIP_TRANSFERRED = 'OwnershipTransferred',\n INITIALIZED = 'Initialized',\n}\n\nexport enum RegistryEventType {\n COMMITTEE_REQUESTED = 'CommitteeRequested',\n COMMITTEE_RANDOMNESS_REQUESTED = 'CommitteeRandomnessRequested',\n RANDOMNESS_CIRCUIT_BREAKER_TRIPPED = 'RandomnessCircuitBreakerTripped',\n COMMITTEE_PUBLISHED = 'CommitteePublished',\n COMMITTEE_FINALIZED = 'SortitionCommitteeFinalized',\n INTERFOLD_SET = 'InterfoldSet',\n OWNERSHIP_TRANSFERRED = 'OwnershipTransferred',\n INITIALIZED = 'Initialized',\n}\n\nexport enum RandomnessProviderEventType {\n RANDOMNESS_FULFILLED = 'RandomnessFulfilled',\n}\n\nexport type AllEventTypes = InterfoldEventType | RegistryEventType\n\nexport interface E3RequestedData {\n e3Id: bigint\n e3: {\n seed: bigint\n committeeSize: number\n requestBlock: bigint\n inputWindow: readonly [bigint, bigint]\n encryptionSchemeId: string\n e3Program: string\n paramSet: number\n decryptionVerifier: string\n committeePublicKey: string\n ciphertextOutput: string\n ciphertextCommitment: string\n plaintextOutput: string\n }\n cryptoConfigId: string\n}\n\nexport interface E3ActivatedData {\n e3Id: bigint\n expiration: bigint\n committeePublicKey: string\n}\n\nexport interface CiphertextOutputPublishedData {\n e3Id: bigint\n ciphertextOutput: string\n ciphertextCommitment: string\n}\n\nexport interface PlaintextOutputPublishedData {\n e3Id: bigint\n plaintextOutput: string\n proof: string\n}\n\nexport interface CiphernodeAddedData {\n node: string\n index: bigint\n numNodes: bigint\n size: bigint\n}\n\nexport interface CiphernodeRemovedData {\n node: string\n index: bigint\n numNodes: bigint\n size: bigint\n}\n\nexport interface CommitteeRequestedData {\n e3Id: bigint\n entropyBlock: bigint\n threshold: [bigint, bigint]\n requestBlock: bigint\n committeeDeadline: bigint\n ticketPrice: bigint\n}\n\nexport interface CommitteeRandomnessRequestedData {\n e3Id: bigint\n requestId: bigint\n provider: string\n randomnessDeadline: bigint\n}\n\nexport interface RandomnessCircuitBreakerTrippedData {\n e3Id: bigint\n requestId: bigint\n randomnessProvider: string\n}\n\nexport interface RandomnessFulfilledData {\n requestId: bigint\n e3Id: bigint\n randomWord: bigint\n fulfilledAt: bigint\n}\n\nexport interface CommitteePublishedData {\n e3Id: bigint\n nodes: string[]\n publicKey: string\n pkCommitment: string\n proof: string\n}\n\nexport interface CommitteeFinalizedData {\n e3Id: bigint\n committee: string[]\n scores: bigint[]\n}\n\nexport interface InterfoldEventData {\n [InterfoldEventType.E3_REQUESTED]: E3RequestedData\n [InterfoldEventType.CIPHERTEXT_OUTPUT_PUBLISHED]: CiphertextOutputPublishedData\n [InterfoldEventType.PLAINTEXT_OUTPUT_PUBLISHED]: PlaintextOutputPublishedData\n [InterfoldEventType.E3_PROGRAM_REGISTERED]: { e3Program: string }\n [InterfoldEventType.ENCRYPTION_SCHEME_ENABLED]: { encryptionSchemeId: string }\n [InterfoldEventType.CIPHERNODE_REGISTRY_SET]: { ciphernodeRegistry: string }\n [InterfoldEventType.MAX_DURATION_SET]: { maxDuration: bigint }\n [InterfoldEventType.PARAM_SET_REGISTERED]: { paramSet: number; encodedParams: string }\n [InterfoldEventType.OWNERSHIP_TRANSFERRED]: { previousOwner: string; newOwner: string }\n [InterfoldEventType.INITIALIZED]: { version: bigint }\n}\n\nexport interface RegistryEventData {\n [RegistryEventType.COMMITTEE_REQUESTED]: CommitteeRequestedData\n [RegistryEventType.COMMITTEE_RANDOMNESS_REQUESTED]: CommitteeRandomnessRequestedData\n [RegistryEventType.RANDOMNESS_CIRCUIT_BREAKER_TRIPPED]: RandomnessCircuitBreakerTrippedData\n [RegistryEventType.COMMITTEE_PUBLISHED]: CommitteePublishedData\n [RegistryEventType.COMMITTEE_FINALIZED]: CommitteeFinalizedData\n [RegistryEventType.INTERFOLD_SET]: { interfold: string }\n [RegistryEventType.OWNERSHIP_TRANSFERRED]: { previousOwner: string; newOwner: string }\n [RegistryEventType.INITIALIZED]: { version: bigint }\n}\n\nexport interface InterfoldEvent<T extends AllEventTypes> {\n type: T\n data: T extends InterfoldEventType ? InterfoldEventData[T] : T extends RegistryEventType ? RegistryEventData[T] : unknown\n log: Log\n timestamp: Date\n blockNumber: bigint\n transactionHash: string\n}\n\nexport interface RandomnessProviderEvent<T extends RandomnessProviderEventType = RandomnessProviderEventType> {\n type: T\n data: RandomnessFulfilledData\n provider: `0x${string}`\n log: Log\n timestamp: Date\n blockNumber: bigint\n transactionHash: string\n}\n\nexport type RandomnessProviderEventCallback<T extends RandomnessProviderEventType = RandomnessProviderEventType> = (\n event: RandomnessProviderEvent<T>,\n) => void | Promise<void>\n\nexport type EventCallback<T extends AllEventTypes = AllEventTypes> = (event: InterfoldEvent<T>) => void | Promise<void>\n\nexport interface EventFilter<T = unknown> {\n address?: `0x${string}`\n fromBlock?: bigint\n toBlock?: bigint\n args?: Partial<T>\n}\n\nexport interface SDKEventEmitter {\n on<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): void\n off<T extends AllEventTypes>(eventType: T, callback: EventCallback<T>): void\n emit<T extends AllEventTypes>(event: InterfoldEvent<T>): void\n}\n\nexport interface EventListenerConfig {\n fromBlock?: bigint\n toBlock?: bigint\n /** Maximum block span for each historical RPC query. */\n historicalBlockRange?: bigint\n polling?: boolean\n pollingInterval?: number\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { type Address, type Hash, type Log, PublicClient, encodeAbiParameters } from 'viem'\nimport type { BfvParams } from './types'\n\nexport class SDKError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n }\n}\n\nexport function isValidAddress(address: string): address is Address {\n return /^0x[a-fA-F0-9]{40}$/.test(address)\n}\n\nexport function isValidHash(hash: string): hash is Hash {\n return /^0x[a-fA-F0-9]{64}$/.test(hash)\n}\n\nexport function formatEventName(contractName: string, eventName: string): string {\n return `${contractName}.${eventName}`\n}\n\nexport function parseEventData<T>(log: Log): T {\n return log.data as unknown as T\n}\n\n/**\n * Sleep for a specified number of milliseconds\n */\nexport const sleep = (ms: number): Promise<void> => {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function formatBigInt(value: bigint): string {\n return value.toString()\n}\n\nexport function parseBigInt(value: string): bigint {\n return BigInt(value)\n}\n\nexport function generateEventId(log: Log): string {\n return `${log.blockHash}-${log.logIndex}`\n}\n\n/**\n * Get the current timestamp in seconds\n * from onchain\n * @param publicClient - The public client to use\n */\nexport async function getCurrentTimestamp(publicClient: PublicClient): Promise<bigint> {\n const block = await publicClient.getBlock()\n return block.timestamp\n}\n\n// Compute provider parameters structure\nexport interface ComputeProviderParams {\n name: string\n parallel: boolean\n batch_size: number\n}\n\n// Default compute provider configuration\nexport const DEFAULT_COMPUTE_PROVIDER_PARAMS: ComputeProviderParams = {\n name: 'risc0',\n parallel: false,\n batch_size: 2,\n}\n\n// Default E3 configuration (`committeeSize` is `IInterfold.CommitteeSize`, not circuit N_PARTIES).\nexport const DEFAULT_E3_CONFIG = {\n committeeSize: 0, // CommitteeSize.Minimum\n duration: 1800, // 30 minutes in seconds\n payment_amount: '0', // 0 ETH in wei\n} as const\n\n/**\n * Encode BFV parameters for the smart contract\n * BFV (Brakerski-Fan-Vercauteren) is a type of fully homomorphic encryption\n */\nexport function encodeBfvParams(params: BfvParams): `0x${string}` {\n const { degree, plaintextModulus, moduli, error1Variance } = params\n\n if (error1Variance === undefined) {\n throw new SDKError(\n 'error1Variance is required in ProtocolParams. All BFV parameter sets must specify error1_variance.',\n 'MISSING_ERROR1_VARIANCE',\n )\n }\n\n return encodeAbiParameters(\n [\n {\n name: 'bfvParams',\n type: 'tuple',\n components: [\n { name: 'degree', type: 'uint256' },\n { name: 'plaintext_modulus', type: 'uint256' },\n { name: 'moduli', type: 'uint256[]' },\n { name: 'error1_variance', type: 'string' },\n ],\n },\n ],\n [\n {\n degree: BigInt(degree),\n plaintext_modulus: BigInt(plaintextModulus),\n moduli: [...moduli],\n error1_variance: error1Variance,\n },\n ],\n )\n}\n\n/**\n * Encode compute provider parameters for the smart contract'\n * If mock is true, the compute provider parameters will return 32 bytes of 0x00\n */\nexport function encodeComputeProviderParams(params: ComputeProviderParams, mock: boolean = false): `0x${string}` {\n if (mock) {\n return `0x${'00'.repeat(32)}` as `0x${string}`\n }\n\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n/**\n * Encode custom parameters for the smart contract.\n */\nexport function encodeCustomParams(params: Record<string, unknown>): `0x${string}` {\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n// inputWindow[0] is always larger than now and dkg deadline\nexport const inputWindowStartBuffer = 15n\n\n/**\n * Calculate start window for E3 request\n * @dev This function can be used for testing purposes, or for E3s which need to start as soon as possible.\n * @param publicClient - The public client to use\n * @param duration - The duration of the input window in seconds\n * @param startBuffer - Buffer in seconds added to current timestamp for input window start\n */\nexport async function calculateInputWindow(\n publicClient: PublicClient,\n duration: number = DEFAULT_E3_CONFIG.duration,\n startBuffer: bigint = inputWindowStartBuffer,\n): Promise<[bigint, bigint]> {\n const now = await getCurrentTimestamp(publicClient)\n return [BigInt(now) + startBuffer, BigInt(now) + startBuffer + BigInt(duration)]\n}\n\n/**\n * Decode plaintextOutput bytes to get the actual result number\n */\nexport function decodePlaintextOutput(plaintextOutput: string): number | null {\n try {\n // Remove '0x' prefix if present\n const hex = plaintextOutput.startsWith('0x') ? plaintextOutput.slice(2) : plaintextOutput\n\n // Convert hex to bytes\n const bytes = new Uint8Array(hex.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) || [])\n\n if (bytes.length < 8) {\n console.warn('Plaintext output too short for u64 decoding')\n return null\n }\n\n // Decode first u64 (8 bytes) as little-endian\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n const result = view.getBigUint64(0, true) // true for little-endian\n\n return Number(result)\n } catch (error) {\n console.error('Failed to decode plaintext output:', error)\n return null\n }\n}\n\n// Helper function to convert proof bytes to field elements\nexport function proofToFields(proof: Uint8Array): string[] {\n const fields: string[] = []\n for (let i = 0; i < proof.length; i += 32) {\n const chunk = proof.slice(i, i + 32)\n fields.push('0x' + Buffer.from(chunk).toString('hex'))\n }\n return fields\n}\n"],"mappings":"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","names":["InterfoldEventType","RegistryEventType","RandomnessProviderEventType"]}
|