@obolnetwork/obol-sdk 2.2.3 → 2.3.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 +1 -1
- package/dist/cjs/src/index.js +13 -0
- package/dist/cjs/src/verification/common.js +5 -10
- package/dist/cjs/src/verification/v1.10.0.js +4 -0
- package/dist/cjs/src/verification/v1.8.0.js +1 -1
- package/dist/cjs/test/fixtures.js +140 -295
- package/dist/cjs/test/methods.test.js +58 -22
- package/dist/esm/package.json +1 -1
- package/dist/esm/src/index.js +13 -0
- package/dist/esm/src/verification/common.js +5 -10
- package/dist/esm/src/verification/v1.10.0.js +5 -1
- package/dist/esm/src/verification/v1.8.0.js +1 -1
- package/dist/esm/test/fixtures.js +139 -294
- package/dist/esm/test/methods.test.js +59 -23
- package/dist/types/src/index.d.ts +7 -1
- package/dist/types/src/types.d.ts +17 -0
- package/dist/types/src/verification/common.d.ts +1 -1
- package/dist/types/src/verification/v1.10.0.d.ts +2 -1
- package/dist/types/test/fixtures.d.ts +55 -0
- package/package.json +1 -1
- package/src/index.ts +16 -0
- package/src/types.ts +23 -0
- package/src/verification/common.ts +8 -12
- package/src/verification/v1.10.0.ts +7 -0
- package/src/verification/v1.8.0.ts +1 -0
|
@@ -7,9 +7,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
var _a, _b;
|
|
10
11
|
import { ethers, JsonRpcProvider } from 'ethers';
|
|
11
12
|
import { Client, validateClusterLock } from '../src/index';
|
|
12
|
-
import { clusterConfigV1X7, clusterConfigV1X8, clusterLockV1X10, clusterLockV1X6, clusterLockV1X7, clusterLockV1X8, clusterLockWithSafe, nullDepositAmountsClusterLockV1X8, } from './fixtures.js';
|
|
13
|
+
import { clusterConfigV1X7, clusterConfigV1X8, clusterLockV1X10, clusterLockV1X6, clusterLockV1X7, clusterLockV1X8, clusterLockWithCompoundingWithdrawals, clusterLockWithSafe, nullDepositAmountsClusterLockV1X8, } from './fixtures.js';
|
|
13
14
|
import { SDK_VERSION } from '../src/constants';
|
|
14
15
|
import { Base } from '../src/base';
|
|
15
16
|
import { validatePayload } from '../src/ajv';
|
|
@@ -19,15 +20,14 @@ import { hashTermsAndConditions } from '../src/verification/termsAndConditions';
|
|
|
19
20
|
import * as utils from '../src/utils';
|
|
20
21
|
import * as splitsHelpers from '../src/splitHelpers';
|
|
21
22
|
jest.setTimeout(20000);
|
|
23
|
+
const mnemonic = (_b = (_a = ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
|
|
24
|
+
const privateKey = ethers.Wallet.fromPhrase(mnemonic).privateKey;
|
|
25
|
+
const provider = new JsonRpcProvider('https://ethereum-holesky.publicnode.com');
|
|
26
|
+
const wallet = new ethers.Wallet(privateKey, provider);
|
|
27
|
+
const mockSigner = wallet.connect(provider);
|
|
22
28
|
/* eslint no-new: 0 */
|
|
23
29
|
describe('Cluster Client', () => {
|
|
24
|
-
var _a, _b;
|
|
25
30
|
const mockConfigHash = '0x1f6c94e6c070393a68c1aa6073a21cb1fd57f0e14d2a475a2958990ab728c2fd';
|
|
26
|
-
const mnemonic = (_b = (_a = ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
|
|
27
|
-
const privateKey = ethers.Wallet.fromPhrase(mnemonic).privateKey;
|
|
28
|
-
const provider = new JsonRpcProvider('https://ethereum-holesky.publicnode.com');
|
|
29
|
-
const wallet = new ethers.Wallet(privateKey, provider);
|
|
30
|
-
const mockSigner = wallet.connect(provider);
|
|
31
31
|
const clientInstance = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
|
|
32
32
|
test('createTermsAndConditions should return "successful authorization"', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
33
33
|
clientInstance['request'] = jest
|
|
@@ -92,12 +92,12 @@ describe('Cluster Client', () => {
|
|
|
92
92
|
}
|
|
93
93
|
}));
|
|
94
94
|
test('getClusterdefinition should return cluster definition if config hash exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
95
|
-
var
|
|
95
|
+
var _a;
|
|
96
96
|
clientInstance['request'] = jest
|
|
97
97
|
.fn()
|
|
98
98
|
.mockReturnValue(Promise.resolve(clusterLockV1X8.cluster_definition));
|
|
99
99
|
const clusterDefinition = yield clientInstance.getClusterDefinition(clusterLockV1X8.cluster_definition.config_hash);
|
|
100
|
-
expect((
|
|
100
|
+
expect((_a = clusterDefinition.deposit_amounts) === null || _a === void 0 ? void 0 : _a.length).toEqual(clusterLockV1X8.cluster_definition.deposit_amounts.length);
|
|
101
101
|
expect(clusterDefinition.config_hash).toEqual(clusterLockV1X8.cluster_definition.config_hash);
|
|
102
102
|
}));
|
|
103
103
|
test('getClusterLock should return lockFile if exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -186,6 +186,10 @@ describe('Cluster Client without a signer', () => {
|
|
|
186
186
|
clusterLock: clusterLockWithSafe,
|
|
187
187
|
},
|
|
188
188
|
{ version: 'v1.10.0', clusterLock: clusterLockV1X10 },
|
|
189
|
+
{
|
|
190
|
+
version: 'v1.10.0 with compunding withdrawals',
|
|
191
|
+
clusterLock: clusterLockWithCompoundingWithdrawals,
|
|
192
|
+
},
|
|
189
193
|
])("$version: 'should return true on verified cluster lock'", ({ clusterLock }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
190
194
|
const isValidLock = yield validateClusterLock(clusterLock);
|
|
191
195
|
expect(isValidLock).toEqual(true);
|
|
@@ -204,9 +208,8 @@ describe('Cluster Client without a signer', () => {
|
|
|
204
208
|
}));
|
|
205
209
|
});
|
|
206
210
|
describe('createObolRewardsSplit', () => {
|
|
207
|
-
let clientInstance, clientInstanceWithourSigner, mockSplitRecipients, mockPrincipalRecipient, mockEtherAmount
|
|
211
|
+
let clientInstance, clientInstanceWithourSigner, mockSplitRecipients, mockPrincipalRecipient, mockEtherAmount;
|
|
208
212
|
beforeAll(() => {
|
|
209
|
-
var _a, _b;
|
|
210
213
|
jest
|
|
211
214
|
.spyOn(utils, 'isContractAvailable')
|
|
212
215
|
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
|
|
@@ -219,11 +222,6 @@ describe('createObolRewardsSplit', () => {
|
|
|
219
222
|
fee_recipient_address: '0xFeeRecipientAddress',
|
|
220
223
|
});
|
|
221
224
|
}));
|
|
222
|
-
const mnemonic = (_b = (_a = ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
|
|
223
|
-
const privateKey = ethers.Wallet.fromPhrase(mnemonic).privateKey;
|
|
224
|
-
const provider = new JsonRpcProvider('https://ethereum-holesky.publicnode.com');
|
|
225
|
-
const wallet = new ethers.Wallet(privateKey, provider);
|
|
226
|
-
mockSigner = wallet.connect(provider);
|
|
227
225
|
clientInstance = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
|
|
228
226
|
clientInstanceWithourSigner = new Client({
|
|
229
227
|
baseUrl: 'https://obol-api-dev.gcp.obol.tech',
|
|
@@ -301,9 +299,8 @@ describe('createObolRewardsSplit', () => {
|
|
|
301
299
|
}));
|
|
302
300
|
});
|
|
303
301
|
describe('createObolTotalSplit', () => {
|
|
304
|
-
let clientInstanceWithourSigner, mockSplitRecipients,
|
|
302
|
+
let clientInstanceWithourSigner, mockSplitRecipients, clientInstance;
|
|
305
303
|
beforeAll(() => {
|
|
306
|
-
var _a, _b;
|
|
307
304
|
jest
|
|
308
305
|
.spyOn(utils, 'isContractAvailable')
|
|
309
306
|
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
|
|
@@ -313,11 +310,6 @@ describe('createObolTotalSplit', () => {
|
|
|
313
310
|
jest
|
|
314
311
|
.spyOn(splitsHelpers, 'deploySplitterContract')
|
|
315
312
|
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xSplitterAddress'); }));
|
|
316
|
-
const mnemonic = (_b = (_a = ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
|
|
317
|
-
const privateKey = ethers.Wallet.fromPhrase(mnemonic).privateKey;
|
|
318
|
-
const provider = new JsonRpcProvider('https://ethereum-holesky.publicnode.com');
|
|
319
|
-
const wallet = new ethers.Wallet(privateKey, provider);
|
|
320
|
-
mockSigner = wallet.connect(provider);
|
|
321
313
|
clientInstance = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
|
|
322
314
|
clientInstanceWithourSigner = new Client({
|
|
323
315
|
baseUrl: 'https://obol-api-dev.gcp.obol.tech',
|
|
@@ -394,3 +386,47 @@ describe('createObolTotalSplit', () => {
|
|
|
394
386
|
});
|
|
395
387
|
}));
|
|
396
388
|
});
|
|
389
|
+
describe('getIncentivesByAddress', () => {
|
|
390
|
+
let clientInstance;
|
|
391
|
+
beforeAll(() => {
|
|
392
|
+
jest
|
|
393
|
+
.spyOn(utils, 'isContractAvailable')
|
|
394
|
+
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
|
|
395
|
+
jest
|
|
396
|
+
.spyOn(splitsHelpers, 'predictSplitterAddress')
|
|
397
|
+
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xPredictedAddress'); }));
|
|
398
|
+
jest
|
|
399
|
+
.spyOn(splitsHelpers, 'deploySplitterContract')
|
|
400
|
+
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xSplitterAddress'); }));
|
|
401
|
+
clientInstance = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
|
|
402
|
+
});
|
|
403
|
+
test('should return incentives for a valid address', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
404
|
+
const mockAddress = '0x1234567890abcdef1234567890abcdef12345678';
|
|
405
|
+
const mockIncentives = {
|
|
406
|
+
operator_address: '0x8c00157cae72c4ed6a1f8bfb60205601f0252e26',
|
|
407
|
+
amount: '100',
|
|
408
|
+
index: 1,
|
|
409
|
+
merkle_proof: ['hash1', 'hash2'],
|
|
410
|
+
contract_address: '0xContract',
|
|
411
|
+
};
|
|
412
|
+
clientInstance['request'] = jest
|
|
413
|
+
.fn()
|
|
414
|
+
.mockReturnValue(Promise.resolve(mockIncentives));
|
|
415
|
+
const incentives = yield clientInstance.getIncentivesByAddress(mockAddress);
|
|
416
|
+
expect(incentives).toEqual(mockIncentives);
|
|
417
|
+
}));
|
|
418
|
+
test('should throw an error if address is not found', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
419
|
+
const invalidAddress = '0x0000000000000000000000000000000000000000';
|
|
420
|
+
clientInstance['request'] = jest
|
|
421
|
+
.fn()
|
|
422
|
+
.mockRejectedValue(new Error('Not found'));
|
|
423
|
+
yield expect(clientInstance.getIncentivesByAddress(invalidAddress)).rejects.toThrow('Not found');
|
|
424
|
+
}));
|
|
425
|
+
test('should throw an error if request fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
426
|
+
const mockAddress = '0x1234567890abcdef1234567890abcdef12345678';
|
|
427
|
+
clientInstance['request'] = jest
|
|
428
|
+
.fn()
|
|
429
|
+
.mockRejectedValue(new Error('Network error'));
|
|
430
|
+
yield expect(clientInstance.getIncentivesByAddress(mockAddress)).rejects.toThrow('Network error');
|
|
431
|
+
}));
|
|
432
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Signer } from 'ethers';
|
|
2
2
|
import { Base } from './base.js';
|
|
3
|
-
import { type RewardsSplitPayload, type ClusterDefinition, type ClusterLock, type ClusterPayload, type OperatorPayload, type TotalSplitPayload, type ClusterValidator, type ETH_ADDRESS, type OWRTranches } from './types.js';
|
|
3
|
+
import { type RewardsSplitPayload, type ClusterDefinition, type ClusterLock, type ClusterPayload, type OperatorPayload, type TotalSplitPayload, type ClusterValidator, type ETH_ADDRESS, type OWRTranches, type Incentives } from './types.js';
|
|
4
4
|
export * from './types.js';
|
|
5
5
|
export * from './services.js';
|
|
6
6
|
export * from './verification/signature-validator.js';
|
|
@@ -112,4 +112,10 @@ export declare class Client extends Base {
|
|
|
112
112
|
* [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89)
|
|
113
113
|
*/
|
|
114
114
|
getClusterLock(configHash: string): Promise<ClusterLock>;
|
|
115
|
+
/**
|
|
116
|
+
* @param address - Operator address
|
|
117
|
+
* @returns {Promise<Incentives>} The matched incentives from DB
|
|
118
|
+
* @throws On not found if address not found.
|
|
119
|
+
*/
|
|
120
|
+
getIncentivesByAddress(address: string): Promise<Incentives>;
|
|
115
121
|
}
|
|
@@ -97,6 +97,8 @@ export interface ClusterDefinition extends ClusterPayload {
|
|
|
97
97
|
consensus_protocol?: string;
|
|
98
98
|
/** The target gas limit where default is 30M. */
|
|
99
99
|
target_gas_limit?: number;
|
|
100
|
+
/** A withdrawal mechanism with 0x02 withdrawal credentials. */
|
|
101
|
+
compounding?: boolean;
|
|
100
102
|
}
|
|
101
103
|
/**
|
|
102
104
|
* Split Recipient Keys
|
|
@@ -209,6 +211,21 @@ export type ClusterLock = {
|
|
|
209
211
|
/** Node Signature for the lock hash by the node secp256k1 key. */
|
|
210
212
|
node_signatures?: string[];
|
|
211
213
|
};
|
|
214
|
+
/**
|
|
215
|
+
* Incentives
|
|
216
|
+
*/
|
|
217
|
+
export type Incentives = {
|
|
218
|
+
/** Operator Address. */
|
|
219
|
+
operator_address: string;
|
|
220
|
+
/** The amount the recipient is entitled to. */
|
|
221
|
+
amount: string;
|
|
222
|
+
/** The recipient’s index in the Merkle tree. */
|
|
223
|
+
index: number;
|
|
224
|
+
/** The Merkle proof (an array of hashes) generated for the recipient. */
|
|
225
|
+
merkle_proof: string[];
|
|
226
|
+
/** The MerkleDistributor contract address. */
|
|
227
|
+
contract_address: string;
|
|
228
|
+
};
|
|
212
229
|
/**
|
|
213
230
|
* String expected to be Ethereum Address
|
|
214
231
|
*/
|
|
@@ -19,7 +19,7 @@ export declare const clusterLockHash: (clusterLock: ClusterLock) => string;
|
|
|
19
19
|
* @param {string} withdrawalAddress - withdrawal address in definition file.
|
|
20
20
|
* @returns {boolean} - return if deposit data is valid.
|
|
21
21
|
*/
|
|
22
|
-
export declare const verifyDepositData: (distributedPublicKey: string, depositData: Partial<DepositData>, withdrawalAddress: string, forkVersion: string) => {
|
|
22
|
+
export declare const verifyDepositData: (distributedPublicKey: string, depositData: Partial<DepositData>, withdrawalAddress: string, forkVersion: string, compounding?: boolean) => {
|
|
23
23
|
isValidDepositData: boolean;
|
|
24
24
|
depositDataMsg: Uint8Array;
|
|
25
25
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UintNumberType } from '@chainsafe/ssz/lib/type/uint';
|
|
2
2
|
import { type creatorAddressWrapperType, type creatorContainerType, type operatorAddressWrapperType, type operatorContainerType, validatorsContainerType } from './sszTypes';
|
|
3
|
-
import { ByteListType, ByteVectorType, ContainerType, ListBasicType, ListCompositeType } from '@chainsafe/ssz';
|
|
3
|
+
import { ByteListType, ByteVectorType, ContainerType, ListBasicType, ListCompositeType, BooleanType } from '@chainsafe/ssz';
|
|
4
4
|
import { type ValueOfFields } from '@chainsafe/ssz/lib/view/container';
|
|
5
5
|
import { type ClusterDefinition, type ClusterLock } from '../types';
|
|
6
6
|
type DefinitionFieldsV1X10 = {
|
|
@@ -18,6 +18,7 @@ type DefinitionFieldsV1X10 = {
|
|
|
18
18
|
deposit_amounts: ListBasicType<UintNumberType>;
|
|
19
19
|
consensus_protocol: ByteListType;
|
|
20
20
|
target_gas_limit: UintNumberType;
|
|
21
|
+
compounding: BooleanType;
|
|
21
22
|
config_hash?: ByteVectorType;
|
|
22
23
|
};
|
|
23
24
|
type DefinitionContainerTypeV1X10 = ContainerType<DefinitionFieldsV1X10>;
|
|
@@ -290,6 +290,61 @@ export declare const clusterLockV1X10: {
|
|
|
290
290
|
deposit_amounts: null;
|
|
291
291
|
consensus_protocol: string;
|
|
292
292
|
target_gas_limit: number;
|
|
293
|
+
compounding: boolean;
|
|
294
|
+
config_hash: string;
|
|
295
|
+
definition_hash: string;
|
|
296
|
+
};
|
|
297
|
+
distributed_validators: {
|
|
298
|
+
distributed_public_key: string;
|
|
299
|
+
public_shares: string[];
|
|
300
|
+
builder_registration: {
|
|
301
|
+
message: {
|
|
302
|
+
fee_recipient: string;
|
|
303
|
+
gas_limit: number;
|
|
304
|
+
timestamp: number;
|
|
305
|
+
pubkey: string;
|
|
306
|
+
};
|
|
307
|
+
signature: string;
|
|
308
|
+
};
|
|
309
|
+
partial_deposit_data: {
|
|
310
|
+
pubkey: string;
|
|
311
|
+
withdrawal_credentials: string;
|
|
312
|
+
amount: string;
|
|
313
|
+
signature: string;
|
|
314
|
+
}[];
|
|
315
|
+
}[];
|
|
316
|
+
signature_aggregate: string;
|
|
317
|
+
lock_hash: string;
|
|
318
|
+
node_signatures: string[];
|
|
319
|
+
};
|
|
320
|
+
export declare const clusterLockWithCompoundingWithdrawals: {
|
|
321
|
+
cluster_definition: {
|
|
322
|
+
name: string;
|
|
323
|
+
creator: {
|
|
324
|
+
address: string;
|
|
325
|
+
config_signature: string;
|
|
326
|
+
};
|
|
327
|
+
operators: {
|
|
328
|
+
address: string;
|
|
329
|
+
enr: string;
|
|
330
|
+
config_signature: string;
|
|
331
|
+
enr_signature: string;
|
|
332
|
+
}[];
|
|
333
|
+
uuid: string;
|
|
334
|
+
version: string;
|
|
335
|
+
timestamp: string;
|
|
336
|
+
num_validators: number;
|
|
337
|
+
threshold: number;
|
|
338
|
+
validators: {
|
|
339
|
+
fee_recipient_address: string;
|
|
340
|
+
withdrawal_address: string;
|
|
341
|
+
}[];
|
|
342
|
+
dkg_algorithm: string;
|
|
343
|
+
fork_version: string;
|
|
344
|
+
deposit_amounts: null;
|
|
345
|
+
consensus_protocol: string;
|
|
346
|
+
target_gas_limit: number;
|
|
347
|
+
compounding: boolean;
|
|
293
348
|
config_hash: string;
|
|
294
349
|
definition_hash: string;
|
|
295
350
|
};
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
type ClusterValidator,
|
|
31
31
|
type ETH_ADDRESS,
|
|
32
32
|
type OWRTranches,
|
|
33
|
+
type Incentives,
|
|
33
34
|
} from './types.js';
|
|
34
35
|
import { clusterConfigOrDefinitionHash } from './verification/common.js';
|
|
35
36
|
import { validatePayload } from './ajv.js';
|
|
@@ -520,4 +521,19 @@ export class Client extends Base {
|
|
|
520
521
|
);
|
|
521
522
|
return lock;
|
|
522
523
|
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* @param address - Operator address
|
|
527
|
+
* @returns {Promise<Incentives>} The matched incentives from DB
|
|
528
|
+
* @throws On not found if address not found.
|
|
529
|
+
*/
|
|
530
|
+
async getIncentivesByAddress(address: string): Promise<Incentives> {
|
|
531
|
+
const incentives: Incentives = await this.request(
|
|
532
|
+
`/${DEFAULT_BASE_VERSION}/address/incentives/${address}`,
|
|
533
|
+
{
|
|
534
|
+
method: 'GET',
|
|
535
|
+
},
|
|
536
|
+
);
|
|
537
|
+
return incentives;
|
|
538
|
+
}
|
|
523
539
|
}
|
package/src/types.ts
CHANGED
|
@@ -144,6 +144,9 @@ export interface ClusterDefinition extends ClusterPayload {
|
|
|
144
144
|
|
|
145
145
|
/** The target gas limit where default is 30M. */
|
|
146
146
|
target_gas_limit?: number;
|
|
147
|
+
|
|
148
|
+
/** A withdrawal mechanism with 0x02 withdrawal credentials. */
|
|
149
|
+
compounding?: boolean;
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
/**
|
|
@@ -290,6 +293,26 @@ export type ClusterLock = {
|
|
|
290
293
|
node_signatures?: string[];
|
|
291
294
|
};
|
|
292
295
|
|
|
296
|
+
/**
|
|
297
|
+
* Incentives
|
|
298
|
+
*/
|
|
299
|
+
export type Incentives = {
|
|
300
|
+
/** Operator Address. */
|
|
301
|
+
operator_address: string;
|
|
302
|
+
|
|
303
|
+
/** The amount the recipient is entitled to. */
|
|
304
|
+
amount: string;
|
|
305
|
+
|
|
306
|
+
/** The recipient’s index in the Merkle tree. */
|
|
307
|
+
index: number;
|
|
308
|
+
|
|
309
|
+
/** The Merkle proof (an array of hashes) generated for the recipient. */
|
|
310
|
+
merkle_proof: string[];
|
|
311
|
+
|
|
312
|
+
/** The MerkleDistributor contract address. */
|
|
313
|
+
contract_address: string;
|
|
314
|
+
};
|
|
315
|
+
|
|
293
316
|
/**
|
|
294
317
|
* String expected to be Ethereum Address
|
|
295
318
|
*/
|
|
@@ -354,23 +354,19 @@ export const verifyDepositData = (
|
|
|
354
354
|
depositData: Partial<DepositData>,
|
|
355
355
|
withdrawalAddress: string,
|
|
356
356
|
forkVersion: string,
|
|
357
|
+
compounding?: boolean,
|
|
357
358
|
): { isValidDepositData: boolean; depositDataMsg: Uint8Array } => {
|
|
358
359
|
const depositDomain = computeDomain(
|
|
359
360
|
fromHexString(DOMAIN_DEPOSIT),
|
|
360
361
|
forkVersion,
|
|
361
362
|
);
|
|
362
|
-
const
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
compoundingWithdrawalPrefix +
|
|
370
|
-
'0'.repeat(22) +
|
|
371
|
-
withdrawalAddress.toLowerCase().slice(2) !==
|
|
372
|
-
depositData.withdrawal_credentials
|
|
373
|
-
) {
|
|
363
|
+
const withdrawalPrefix = compounding ? '0x02' : '0x01';
|
|
364
|
+
const expectedWithdrawalCredentials =
|
|
365
|
+
withdrawalPrefix +
|
|
366
|
+
'0'.repeat(22) +
|
|
367
|
+
withdrawalAddress.toLowerCase().slice(2);
|
|
368
|
+
|
|
369
|
+
if (expectedWithdrawalCredentials !== depositData.withdrawal_credentials) {
|
|
374
370
|
return { isValidDepositData: false, depositDataMsg: new Uint8Array(0) };
|
|
375
371
|
}
|
|
376
372
|
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
ListBasicType,
|
|
22
22
|
ListCompositeType,
|
|
23
23
|
fromHexString,
|
|
24
|
+
BooleanType,
|
|
24
25
|
} from '@chainsafe/ssz';
|
|
25
26
|
import { type ValueOfFields } from '@chainsafe/ssz/lib/view/container';
|
|
26
27
|
import {
|
|
@@ -48,6 +49,7 @@ type DefinitionFieldsV1X10 = {
|
|
|
48
49
|
deposit_amounts: ListBasicType<UintNumberType>;
|
|
49
50
|
consensus_protocol: ByteListType;
|
|
50
51
|
target_gas_limit: UintNumberType;
|
|
52
|
+
compounding: BooleanType;
|
|
51
53
|
config_hash?: ByteVectorType;
|
|
52
54
|
};
|
|
53
55
|
|
|
@@ -79,6 +81,7 @@ export const clusterDefinitionContainerTypeV1X10 = (
|
|
|
79
81
|
),
|
|
80
82
|
consensus_protocol: new ByteListType(256),
|
|
81
83
|
target_gas_limit: new UintNumberType(8 as UintNumberByteLen),
|
|
84
|
+
compounding: new BooleanType(),
|
|
82
85
|
};
|
|
83
86
|
|
|
84
87
|
if (!configOnly) {
|
|
@@ -144,6 +147,10 @@ export const hashClusterDefinitionV1X10 = (
|
|
|
144
147
|
val.target_gas_limit = cluster.target_gas_limit;
|
|
145
148
|
}
|
|
146
149
|
|
|
150
|
+
if (cluster.compounding) {
|
|
151
|
+
val.compounding = cluster.compounding;
|
|
152
|
+
}
|
|
153
|
+
|
|
147
154
|
if (!configOnly) {
|
|
148
155
|
val.config_hash = fromHexString(cluster.config_hash);
|
|
149
156
|
}
|
|
@@ -259,6 +259,7 @@ export const verifyDVV1X8 = (clusterLock: ClusterLock): boolean => {
|
|
|
259
259
|
depositData as Partial<DepositData>,
|
|
260
260
|
clusterLock.cluster_definition.validators[i].withdrawal_address,
|
|
261
261
|
clusterLock.cluster_definition.fork_version,
|
|
262
|
+
clusterLock.cluster_definition.compounding,
|
|
262
263
|
);
|
|
263
264
|
|
|
264
265
|
if (!isValidDepositData) {
|