@obolnetwork/obol-sdk 2.5.0 → 2.6.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/dist/cjs/package.json +3 -3
- package/dist/cjs/src/constants.js +13 -1
- package/dist/cjs/src/exits/ethUtils.js +57 -0
- package/dist/cjs/src/exits/exit.js +420 -0
- package/dist/cjs/src/exits/verificationHelpers.js +86 -0
- package/dist/cjs/src/{incentiveHelpers.js → incentives/incentiveHelpers.js} +1 -1
- package/dist/cjs/src/{incentives.js → incentives/incentives.js} +3 -3
- package/dist/cjs/src/index.js +22 -4
- package/dist/cjs/src/schema.js +1 -1
- package/dist/cjs/src/splits/splitHelpers.js +327 -0
- package/dist/cjs/src/types.js +1 -0
- package/dist/cjs/test/exit/ethUtils.spec.js +83 -0
- package/dist/cjs/test/exit/exit.spec.js +328 -0
- package/dist/cjs/test/exit/verificationHelpers.spec.js +68 -0
- package/dist/cjs/test/{incentives.test.js → incentives/incentives.spec.js} +4 -4
- package/dist/esm/package.json +3 -3
- package/dist/esm/src/constants.js +12 -0
- package/dist/esm/src/exits/ethUtils.js +52 -0
- package/dist/esm/src/exits/exit.js +393 -0
- package/dist/esm/src/exits/verificationHelpers.js +81 -0
- package/dist/esm/src/{incentiveHelpers.js → incentives/incentiveHelpers.js} +1 -1
- package/dist/esm/src/{incentives.js → incentives/incentives.js} +3 -3
- package/dist/esm/src/index.js +20 -3
- package/dist/esm/src/schema.js +1 -1
- package/dist/esm/src/splits/splitHelpers.js +317 -0
- package/dist/esm/src/types.js +1 -0
- package/dist/esm/test/exit/ethUtils.spec.js +81 -0
- package/dist/esm/test/exit/exit.spec.js +303 -0
- package/dist/esm/test/exit/verificationHelpers.spec.js +66 -0
- package/dist/esm/test/{incentives.test.js → incentives/incentives.spec.js} +4 -4
- package/dist/types/src/constants.d.ts +5 -0
- package/dist/types/src/exits/ethUtils.d.ts +13 -0
- package/dist/types/src/exits/exit.d.ts +180 -0
- package/dist/types/src/exits/verificationHelpers.d.ts +20 -0
- package/dist/types/src/{incentiveHelpers.d.ts → incentives/incentiveHelpers.d.ts} +1 -1
- package/dist/types/src/{incentives.d.ts → incentives/incentives.d.ts} +1 -1
- package/dist/types/src/index.d.ts +16 -2
- package/dist/types/src/{splitHelpers.d.ts → splits/splitHelpers.d.ts} +1 -1
- package/dist/types/src/types.d.ts +98 -0
- package/dist/types/test/exit/verificationHelpers.spec.d.ts +1 -0
- package/dist/types/test/incentives/incentives.spec.d.ts +1 -0
- package/package.json +3 -3
- package/src/constants.ts +13 -0
- package/src/exits/ethUtils.ts +49 -0
- package/src/exits/exit.ts +564 -0
- package/src/exits/verificationHelpers.ts +110 -0
- package/src/{incentiveHelpers.ts → incentives/incentiveHelpers.ts} +2 -2
- package/src/{incentives.ts → incentives/incentives.ts} +3 -3
- package/src/index.ts +29 -3
- package/src/schema.ts +1 -1
- package/src/splits/splitHelpers.ts +557 -0
- package/src/types.ts +123 -0
- package/dist/cjs/src/splitHelpers.js +0 -187
- package/dist/cjs/test/methods.test.js +0 -418
- package/dist/esm/src/splitHelpers.js +0 -177
- package/dist/esm/test/methods.test.js +0 -393
- package/src/splitHelpers.ts +0 -355
- /package/dist/types/test/{incentives.test.d.ts → exit/ethUtils.spec.d.ts} +0 -0
- /package/dist/types/test/{methods.test.d.ts → exit/exit.spec.d.ts} +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Base } from './base.js';
|
|
2
2
|
import { type RewardsSplitPayload, type ClusterDefinition, type ClusterLock, type ClusterPayload, type OperatorPayload, type TotalSplitPayload, type ClusterValidator, type ETH_ADDRESS, type OWRTranches, type ProviderType, type SignerType } from './types.js';
|
|
3
|
-
import { Incentives } from './incentives.js';
|
|
3
|
+
import { Incentives } from './incentives/incentives.js';
|
|
4
|
+
import { Exit } from './exits/exit.js';
|
|
4
5
|
export * from './types.js';
|
|
5
6
|
export * from './services.js';
|
|
6
7
|
export * from './verification/signature-validator.js';
|
|
7
8
|
export * from './verification/common.js';
|
|
8
9
|
export * from './constants.js';
|
|
9
|
-
export { Incentives } from './incentives.js';
|
|
10
|
+
export { Incentives } from './incentives/incentives.js';
|
|
11
|
+
export { Exit } from './exits/exit.js';
|
|
10
12
|
/**
|
|
11
13
|
* Obol sdk Client can be used for creating, managing and activating distributed validators.
|
|
12
14
|
*/
|
|
@@ -20,6 +22,11 @@ export declare class Client extends Base {
|
|
|
20
22
|
* @type {Incentives}
|
|
21
23
|
*/
|
|
22
24
|
incentives: Incentives;
|
|
25
|
+
/**
|
|
26
|
+
* The exit module, responsible for managing exit validation.
|
|
27
|
+
* @type {Exit}
|
|
28
|
+
*/
|
|
29
|
+
exit: Exit;
|
|
23
30
|
/**
|
|
24
31
|
* The blockchain provider, used to interact with the network.
|
|
25
32
|
* It can be null, undefined, or a valid provider instance and defaults to the Signer provider if Signer is passed.
|
|
@@ -127,4 +134,11 @@ export declare class Client extends Base {
|
|
|
127
134
|
* [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89)
|
|
128
135
|
*/
|
|
129
136
|
getClusterLock(configHash: string): Promise<ClusterLock>;
|
|
137
|
+
/**
|
|
138
|
+
* @param lockHash - The configuration hash in cluster-definition
|
|
139
|
+
* @returns {Promise<ClusterLock>} The matched cluster details (lock) from DB
|
|
140
|
+
* @throws On not found cluster definition or lock.
|
|
141
|
+
*
|
|
142
|
+
*/
|
|
143
|
+
getClusterLockByHash(lockHash: string): Promise<ClusterLock>;
|
|
130
144
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type OWRTranches, type ClusterValidator, type ETH_ADDRESS, type SplitRecipient, type SignerType } from '
|
|
1
|
+
import { type OWRTranches, type ClusterValidator, type ETH_ADDRESS, type SplitRecipient, type SignerType } from '../types';
|
|
2
2
|
type Call = {
|
|
3
3
|
target: ETH_ADDRESS;
|
|
4
4
|
callData: string;
|
|
@@ -254,3 +254,101 @@ export type SignerType = Signer | JsonRpcSigner | Wallet;
|
|
|
254
254
|
export type ClaimIncentivesResponse = {
|
|
255
255
|
txHash: string | null;
|
|
256
256
|
};
|
|
257
|
+
/**
|
|
258
|
+
* Represents the structure of an Ethereum operator for exit validation, primarily their ENR.
|
|
259
|
+
*/
|
|
260
|
+
export interface ExitOperator {
|
|
261
|
+
/** The operator's Ethereum Node Record (ENR). */
|
|
262
|
+
enr: string;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Represents the core definition of a cluster relevant for exit validation.
|
|
266
|
+
*/
|
|
267
|
+
export interface ExitClusterDefinition {
|
|
268
|
+
/** The cluster nodes operators with their ENRs. */
|
|
269
|
+
operators: ExitOperator[];
|
|
270
|
+
/** The cluster fork version. */
|
|
271
|
+
fork_version: string;
|
|
272
|
+
/** The distributed validator threshold. */
|
|
273
|
+
threshold: number;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Represents a distributed validator's information relevant for exit validation.
|
|
277
|
+
*/
|
|
278
|
+
export interface ExitDistributedValidator {
|
|
279
|
+
/** The public key of the distributed validator. */
|
|
280
|
+
distributed_public_key: string;
|
|
281
|
+
/** The public key shares of the distributed validator. */
|
|
282
|
+
public_shares: string[];
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Combined cluster information needed for exit validation in the SDK.
|
|
286
|
+
*/
|
|
287
|
+
export interface ExitClusterConfig {
|
|
288
|
+
/** The cluster definition with operators, fork version and threshold. */
|
|
289
|
+
definition: ExitClusterDefinition;
|
|
290
|
+
/** The cluster distributed validators. */
|
|
291
|
+
distributed_validators: ExitDistributedValidator[];
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Represents the message part of a signed exit for exit validation.
|
|
295
|
+
*/
|
|
296
|
+
export interface ExitValidationMessage {
|
|
297
|
+
/** The epoch at which the validator wishes to exit. */
|
|
298
|
+
epoch: string;
|
|
299
|
+
/** The index of the validator in the beacon chain. */
|
|
300
|
+
validator_index: string;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Represents a signed exit message for exit validation.
|
|
304
|
+
*/
|
|
305
|
+
export interface SignedExitValidationMessage {
|
|
306
|
+
/** The exit message containing epoch and validator index. */
|
|
307
|
+
message: ExitValidationMessage;
|
|
308
|
+
/** BLS signature of the exit message. */
|
|
309
|
+
signature: string;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Represents a single partial exit blob for exit validation.
|
|
313
|
+
*/
|
|
314
|
+
export interface ExitValidationBlob {
|
|
315
|
+
/** The public key of the validator to exit. */
|
|
316
|
+
public_key: string;
|
|
317
|
+
/** The signed exit message for the validator. */
|
|
318
|
+
signed_exit_message: SignedExitValidationMessage;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Represents the overall exit payload structure for exit validation.
|
|
322
|
+
*/
|
|
323
|
+
export interface ExitValidationPayload {
|
|
324
|
+
/** Array of partial exits for validators. */
|
|
325
|
+
partial_exits: ExitValidationBlob[];
|
|
326
|
+
/** Operator's share index (1-based). */
|
|
327
|
+
share_idx: number;
|
|
328
|
+
/** Signature of the ExitValidationPayload by the operator. */
|
|
329
|
+
signature: string;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Represents the data structure for an already existing exit blob for exit validation.
|
|
333
|
+
*/
|
|
334
|
+
export interface ExistingExitValidationBlobData {
|
|
335
|
+
/** The public key of the validator to exit. */
|
|
336
|
+
public_key: string;
|
|
337
|
+
/** The epoch at which the validator wishes to exit. */
|
|
338
|
+
epoch: string;
|
|
339
|
+
/** The index of the validator in the beacon chain. */
|
|
340
|
+
validator_index: string;
|
|
341
|
+
/** Collection of partial exit signatures from different shares. */
|
|
342
|
+
shares_exit_data: Array<Record<string, {
|
|
343
|
+
partial_exit_signature: string;
|
|
344
|
+
}>>;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Generic HTTP request function type.
|
|
348
|
+
* Args:
|
|
349
|
+
* url: string - The URL to request.
|
|
350
|
+
* config?: Record<string, any> - Optional request configuration (e.g., method, headers, body for POST).
|
|
351
|
+
* Returns:
|
|
352
|
+
* Promise<any> - The response data.
|
|
353
|
+
*/
|
|
354
|
+
export type HttpRequestFunc = (url: string, config?: Record<string, any>) => Promise<any>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obolnetwork/obol-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "A package for creating Distributed Validators using the Obol API.",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/obolnetwork/obol-sdk/issues"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"compile": "tsc -b ./tsconfig.cjs.json ./tsconfig.esm.json ./tsconfig.types.json",
|
|
16
16
|
"build:clean": "rm -rf ./dist",
|
|
17
17
|
"build": "npm-run-all build:clean compile",
|
|
18
|
-
"test": "jest
|
|
18
|
+
"test": "jest test/**/*.spec.ts --testPathIgnorePatterns=test/sdk-package/",
|
|
19
19
|
"generate-typedoc": "typedoc",
|
|
20
20
|
"npm:publish": "npm publish --tag latest",
|
|
21
21
|
"release": "release-it",
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
"^bn.js$": "<rootDir>/node_modules/bn.js",
|
|
131
131
|
"^asn1.js$": "<rootDir>/node_modules/asn1.js",
|
|
132
132
|
"^hash.js$": "<rootDir>/node_modules/hash.js",
|
|
133
|
-
"(
|
|
133
|
+
"^(\\.\\.?\\/.+)\\.js$": "$1"
|
|
134
134
|
},
|
|
135
135
|
"extensionsToTreatAsEsm": [
|
|
136
136
|
".ts"
|
package/src/constants.ts
CHANGED
|
@@ -205,3 +205,16 @@ export const PROVIDER_MAP: Record<number, string> = {
|
|
|
205
205
|
11155111: `${process.env.RPC_SEPOLIA}`, // Sepolia
|
|
206
206
|
100: `${process.env.RPC_GNOSIS}`, // Gnosis
|
|
207
207
|
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Maps base fork versions to their corresponding Capella fork versions.
|
|
211
|
+
* Example: Mainnet Capella fork version.
|
|
212
|
+
*/
|
|
213
|
+
export const CAPELLA_FORK_MAPPING: Record<string, string> = {
|
|
214
|
+
'0x00000000': '0x03000000', // Mainnet
|
|
215
|
+
'0x00001020': '0x03001020', // Goerli
|
|
216
|
+
'0x00000064': '0x03000064', // Gnosis
|
|
217
|
+
'0x90000069': '0x90000072', // Sepolia
|
|
218
|
+
'0x01017000': '0x04017000', // Holesky
|
|
219
|
+
'0x10000910': '0x40000910', // Hoodi
|
|
220
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CAPELLA_FORK_MAPPING } from '../constants';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Retrieves the Capella fork version for a given base fork version.
|
|
5
|
+
* @param fork_version - The base fork version string (e.g., '0x00000000' for mainnet).
|
|
6
|
+
* @returns A promise that resolves to the Capella fork version string, or null if not found.
|
|
7
|
+
*/
|
|
8
|
+
export async function getCapellaFork(
|
|
9
|
+
fork_version: string,
|
|
10
|
+
): Promise<string | null> {
|
|
11
|
+
// Ensure the CAPELLA_FORK_MAPPING uses the base fork_version as key
|
|
12
|
+
if (CAPELLA_FORK_MAPPING[fork_version]) {
|
|
13
|
+
return CAPELLA_FORK_MAPPING[fork_version];
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Fetches the genesis validators root from a beacon node.
|
|
20
|
+
* @param beaconNodeApiUrl - The base URL of the beacon node API (e.g., http://localhost:5052).
|
|
21
|
+
* @returns A promise that resolves to the genesis_validators_root string, or null on error.
|
|
22
|
+
* @throws Will throw an error if the network corresponding to the fork_version is not supported or if the HTTP request fails.
|
|
23
|
+
*/
|
|
24
|
+
export async function getGenesisValidatorsRoot(
|
|
25
|
+
beaconNodeApiUrl: string,
|
|
26
|
+
): Promise<string | null> {
|
|
27
|
+
const genesisEndpoint = `${beaconNodeApiUrl}/eth/v1/beacon/genesis`;
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const response = await fetch(genesisEndpoint, {
|
|
31
|
+
method: 'GET',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const json = await response.json();
|
|
35
|
+
|
|
36
|
+
if (json.data?.genesis_validators_root) {
|
|
37
|
+
return json.data.genesis_validators_root;
|
|
38
|
+
}
|
|
39
|
+
console.error('Invalid response structure from genesis endpoint', json);
|
|
40
|
+
return null;
|
|
41
|
+
} catch (e: any) {
|
|
42
|
+
console.error(
|
|
43
|
+
`Error fetching genesis validators root from ${genesisEndpoint}:`,
|
|
44
|
+
e,
|
|
45
|
+
);
|
|
46
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
47
|
+
throw new Error(`Failed to fetch genesis validators root: ${errorMessage}`);
|
|
48
|
+
}
|
|
49
|
+
}
|