@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
|
@@ -31,6 +31,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
31
31
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
32
|
});
|
|
33
33
|
};
|
|
34
|
+
var _a, _b;
|
|
34
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
36
|
const ethers_1 = require("ethers");
|
|
36
37
|
const index_1 = require("../src/index");
|
|
@@ -44,15 +45,14 @@ const termsAndConditions_1 = require("../src/verification/termsAndConditions");
|
|
|
44
45
|
const utils = __importStar(require("../src/utils"));
|
|
45
46
|
const splitsHelpers = __importStar(require("../src/splitHelpers"));
|
|
46
47
|
jest.setTimeout(20000);
|
|
48
|
+
const mnemonic = (_b = (_a = ethers_1.ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
|
|
49
|
+
const privateKey = ethers_1.ethers.Wallet.fromPhrase(mnemonic).privateKey;
|
|
50
|
+
const provider = new ethers_1.JsonRpcProvider('https://ethereum-holesky.publicnode.com');
|
|
51
|
+
const wallet = new ethers_1.ethers.Wallet(privateKey, provider);
|
|
52
|
+
const mockSigner = wallet.connect(provider);
|
|
47
53
|
/* eslint no-new: 0 */
|
|
48
54
|
describe('Cluster Client', () => {
|
|
49
|
-
var _a, _b;
|
|
50
55
|
const mockConfigHash = '0x1f6c94e6c070393a68c1aa6073a21cb1fd57f0e14d2a475a2958990ab728c2fd';
|
|
51
|
-
const mnemonic = (_b = (_a = ethers_1.ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
|
|
52
|
-
const privateKey = ethers_1.ethers.Wallet.fromPhrase(mnemonic).privateKey;
|
|
53
|
-
const provider = new ethers_1.JsonRpcProvider('https://ethereum-holesky.publicnode.com');
|
|
54
|
-
const wallet = new ethers_1.ethers.Wallet(privateKey, provider);
|
|
55
|
-
const mockSigner = wallet.connect(provider);
|
|
56
56
|
const clientInstance = new index_1.Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
|
|
57
57
|
test('createTermsAndConditions should return "successful authorization"', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
58
|
clientInstance['request'] = jest
|
|
@@ -117,12 +117,12 @@ describe('Cluster Client', () => {
|
|
|
117
117
|
}
|
|
118
118
|
}));
|
|
119
119
|
test('getClusterdefinition should return cluster definition if config hash exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
120
|
-
var
|
|
120
|
+
var _a;
|
|
121
121
|
clientInstance['request'] = jest
|
|
122
122
|
.fn()
|
|
123
123
|
.mockReturnValue(Promise.resolve(fixtures_js_1.clusterLockV1X8.cluster_definition));
|
|
124
124
|
const clusterDefinition = yield clientInstance.getClusterDefinition(fixtures_js_1.clusterLockV1X8.cluster_definition.config_hash);
|
|
125
|
-
expect((
|
|
125
|
+
expect((_a = clusterDefinition.deposit_amounts) === null || _a === void 0 ? void 0 : _a.length).toEqual(fixtures_js_1.clusterLockV1X8.cluster_definition.deposit_amounts.length);
|
|
126
126
|
expect(clusterDefinition.config_hash).toEqual(fixtures_js_1.clusterLockV1X8.cluster_definition.config_hash);
|
|
127
127
|
}));
|
|
128
128
|
test('getClusterLock should return lockFile if exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -211,6 +211,10 @@ describe('Cluster Client without a signer', () => {
|
|
|
211
211
|
clusterLock: fixtures_js_1.clusterLockWithSafe,
|
|
212
212
|
},
|
|
213
213
|
{ version: 'v1.10.0', clusterLock: fixtures_js_1.clusterLockV1X10 },
|
|
214
|
+
{
|
|
215
|
+
version: 'v1.10.0 with compunding withdrawals',
|
|
216
|
+
clusterLock: fixtures_js_1.clusterLockWithCompoundingWithdrawals,
|
|
217
|
+
},
|
|
214
218
|
])("$version: 'should return true on verified cluster lock'", ({ clusterLock }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
215
219
|
const isValidLock = yield (0, index_1.validateClusterLock)(clusterLock);
|
|
216
220
|
expect(isValidLock).toEqual(true);
|
|
@@ -229,9 +233,8 @@ describe('Cluster Client without a signer', () => {
|
|
|
229
233
|
}));
|
|
230
234
|
});
|
|
231
235
|
describe('createObolRewardsSplit', () => {
|
|
232
|
-
let clientInstance, clientInstanceWithourSigner, mockSplitRecipients, mockPrincipalRecipient, mockEtherAmount
|
|
236
|
+
let clientInstance, clientInstanceWithourSigner, mockSplitRecipients, mockPrincipalRecipient, mockEtherAmount;
|
|
233
237
|
beforeAll(() => {
|
|
234
|
-
var _a, _b;
|
|
235
238
|
jest
|
|
236
239
|
.spyOn(utils, 'isContractAvailable')
|
|
237
240
|
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
|
|
@@ -244,11 +247,6 @@ describe('createObolRewardsSplit', () => {
|
|
|
244
247
|
fee_recipient_address: '0xFeeRecipientAddress',
|
|
245
248
|
});
|
|
246
249
|
}));
|
|
247
|
-
const mnemonic = (_b = (_a = ethers_1.ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
|
|
248
|
-
const privateKey = ethers_1.ethers.Wallet.fromPhrase(mnemonic).privateKey;
|
|
249
|
-
const provider = new ethers_1.JsonRpcProvider('https://ethereum-holesky.publicnode.com');
|
|
250
|
-
const wallet = new ethers_1.ethers.Wallet(privateKey, provider);
|
|
251
|
-
mockSigner = wallet.connect(provider);
|
|
252
250
|
clientInstance = new index_1.Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
|
|
253
251
|
clientInstanceWithourSigner = new index_1.Client({
|
|
254
252
|
baseUrl: 'https://obol-api-dev.gcp.obol.tech',
|
|
@@ -326,9 +324,8 @@ describe('createObolRewardsSplit', () => {
|
|
|
326
324
|
}));
|
|
327
325
|
});
|
|
328
326
|
describe('createObolTotalSplit', () => {
|
|
329
|
-
let clientInstanceWithourSigner, mockSplitRecipients,
|
|
327
|
+
let clientInstanceWithourSigner, mockSplitRecipients, clientInstance;
|
|
330
328
|
beforeAll(() => {
|
|
331
|
-
var _a, _b;
|
|
332
329
|
jest
|
|
333
330
|
.spyOn(utils, 'isContractAvailable')
|
|
334
331
|
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
|
|
@@ -338,11 +335,6 @@ describe('createObolTotalSplit', () => {
|
|
|
338
335
|
jest
|
|
339
336
|
.spyOn(splitsHelpers, 'deploySplitterContract')
|
|
340
337
|
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xSplitterAddress'); }));
|
|
341
|
-
const mnemonic = (_b = (_a = ethers_1.ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
|
|
342
|
-
const privateKey = ethers_1.ethers.Wallet.fromPhrase(mnemonic).privateKey;
|
|
343
|
-
const provider = new ethers_1.JsonRpcProvider('https://ethereum-holesky.publicnode.com');
|
|
344
|
-
const wallet = new ethers_1.ethers.Wallet(privateKey, provider);
|
|
345
|
-
mockSigner = wallet.connect(provider);
|
|
346
338
|
clientInstance = new index_1.Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
|
|
347
339
|
clientInstanceWithourSigner = new index_1.Client({
|
|
348
340
|
baseUrl: 'https://obol-api-dev.gcp.obol.tech',
|
|
@@ -419,3 +411,47 @@ describe('createObolTotalSplit', () => {
|
|
|
419
411
|
});
|
|
420
412
|
}));
|
|
421
413
|
});
|
|
414
|
+
describe('getIncentivesByAddress', () => {
|
|
415
|
+
let clientInstance;
|
|
416
|
+
beforeAll(() => {
|
|
417
|
+
jest
|
|
418
|
+
.spyOn(utils, 'isContractAvailable')
|
|
419
|
+
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
|
|
420
|
+
jest
|
|
421
|
+
.spyOn(splitsHelpers, 'predictSplitterAddress')
|
|
422
|
+
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xPredictedAddress'); }));
|
|
423
|
+
jest
|
|
424
|
+
.spyOn(splitsHelpers, 'deploySplitterContract')
|
|
425
|
+
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xSplitterAddress'); }));
|
|
426
|
+
clientInstance = new index_1.Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
|
|
427
|
+
});
|
|
428
|
+
test('should return incentives for a valid address', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
429
|
+
const mockAddress = '0x1234567890abcdef1234567890abcdef12345678';
|
|
430
|
+
const mockIncentives = {
|
|
431
|
+
operator_address: '0x8c00157cae72c4ed6a1f8bfb60205601f0252e26',
|
|
432
|
+
amount: '100',
|
|
433
|
+
index: 1,
|
|
434
|
+
merkle_proof: ['hash1', 'hash2'],
|
|
435
|
+
contract_address: '0xContract',
|
|
436
|
+
};
|
|
437
|
+
clientInstance['request'] = jest
|
|
438
|
+
.fn()
|
|
439
|
+
.mockReturnValue(Promise.resolve(mockIncentives));
|
|
440
|
+
const incentives = yield clientInstance.getIncentivesByAddress(mockAddress);
|
|
441
|
+
expect(incentives).toEqual(mockIncentives);
|
|
442
|
+
}));
|
|
443
|
+
test('should throw an error if address is not found', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
444
|
+
const invalidAddress = '0x0000000000000000000000000000000000000000';
|
|
445
|
+
clientInstance['request'] = jest
|
|
446
|
+
.fn()
|
|
447
|
+
.mockRejectedValue(new Error('Not found'));
|
|
448
|
+
yield expect(clientInstance.getIncentivesByAddress(invalidAddress)).rejects.toThrow('Not found');
|
|
449
|
+
}));
|
|
450
|
+
test('should throw an error if request fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
451
|
+
const mockAddress = '0x1234567890abcdef1234567890abcdef12345678';
|
|
452
|
+
clientInstance['request'] = jest
|
|
453
|
+
.fn()
|
|
454
|
+
.mockRejectedValue(new Error('Network error'));
|
|
455
|
+
yield expect(clientInstance.getIncentivesByAddress(mockAddress)).rejects.toThrow('Network error');
|
|
456
|
+
}));
|
|
457
|
+
});
|
package/dist/esm/package.json
CHANGED
package/dist/esm/src/index.js
CHANGED
|
@@ -353,4 +353,17 @@ export class Client extends Base {
|
|
|
353
353
|
return lock;
|
|
354
354
|
});
|
|
355
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* @param address - Operator address
|
|
358
|
+
* @returns {Promise<Incentives>} The matched incentives from DB
|
|
359
|
+
* @throws On not found if address not found.
|
|
360
|
+
*/
|
|
361
|
+
getIncentivesByAddress(address) {
|
|
362
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
363
|
+
const incentives = yield this.request(`/${DEFAULT_BASE_VERSION}/address/incentives/${address}`, {
|
|
364
|
+
method: 'GET',
|
|
365
|
+
});
|
|
366
|
+
return incentives;
|
|
367
|
+
});
|
|
368
|
+
}
|
|
356
369
|
}
|
|
@@ -208,18 +208,13 @@ const computeDomain = (domainType, lockForkVersion, genesisValidatorsRoot = from
|
|
|
208
208
|
* @param {string} withdrawalAddress - withdrawal address in definition file.
|
|
209
209
|
* @returns {boolean} - return if deposit data is valid.
|
|
210
210
|
*/
|
|
211
|
-
export const verifyDepositData = (distributedPublicKey, depositData, withdrawalAddress, forkVersion) => {
|
|
211
|
+
export const verifyDepositData = (distributedPublicKey, depositData, withdrawalAddress, forkVersion, compounding) => {
|
|
212
212
|
const depositDomain = computeDomain(fromHexString(DOMAIN_DEPOSIT), forkVersion);
|
|
213
|
-
const
|
|
214
|
-
const
|
|
215
|
-
if (eth1AddressWithdrawalPrefix +
|
|
213
|
+
const withdrawalPrefix = compounding ? '0x02' : '0x01';
|
|
214
|
+
const expectedWithdrawalCredentials = withdrawalPrefix +
|
|
216
215
|
'0'.repeat(22) +
|
|
217
|
-
withdrawalAddress.toLowerCase().slice(2)
|
|
218
|
-
|
|
219
|
-
compoundingWithdrawalPrefix +
|
|
220
|
-
'0'.repeat(22) +
|
|
221
|
-
withdrawalAddress.toLowerCase().slice(2) !==
|
|
222
|
-
depositData.withdrawal_credentials) {
|
|
216
|
+
withdrawalAddress.toLowerCase().slice(2);
|
|
217
|
+
if (expectedWithdrawalCredentials !== depositData.withdrawal_credentials) {
|
|
223
218
|
return { isValidDepositData: false, depositDataMsg: new Uint8Array(0) };
|
|
224
219
|
}
|
|
225
220
|
if (distributedPublicKey !== depositData.pubkey) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { UintNumberType, } from '@chainsafe/ssz/lib/type/uint';
|
|
2
2
|
import { strToUint8Array } from '../utils';
|
|
3
3
|
import { builderRegistrationContainer, depositDataContainer, newCreatorContainerType, newOperatorContainerType, validatorsContainerType, } from './sszTypes';
|
|
4
|
-
import { ByteListType, ByteVectorType, ContainerType, ListBasicType, ListCompositeType, fromHexString, } from '@chainsafe/ssz';
|
|
4
|
+
import { ByteListType, ByteVectorType, ContainerType, ListBasicType, ListCompositeType, fromHexString, BooleanType, } from '@chainsafe/ssz';
|
|
5
5
|
import { verifyDVV1X8 } from './v1.8.0';
|
|
6
6
|
/**
|
|
7
7
|
* Returns the containerized cluster definition
|
|
@@ -24,6 +24,7 @@ export const clusterDefinitionContainerTypeV1X10 = (configOnly) => {
|
|
|
24
24
|
deposit_amounts: new ListBasicType(new UintNumberType(8), 256),
|
|
25
25
|
consensus_protocol: new ByteListType(256),
|
|
26
26
|
target_gas_limit: new UintNumberType(8),
|
|
27
|
+
compounding: new BooleanType(),
|
|
27
28
|
};
|
|
28
29
|
if (!configOnly) {
|
|
29
30
|
returnedContainerType = Object.assign(Object.assign({}, returnedContainerType), { config_hash: new ByteVectorType(32) });
|
|
@@ -75,6 +76,9 @@ export const hashClusterDefinitionV1X10 = (cluster, configOnly) => {
|
|
|
75
76
|
if (cluster.target_gas_limit) {
|
|
76
77
|
val.target_gas_limit = cluster.target_gas_limit;
|
|
77
78
|
}
|
|
79
|
+
if (cluster.compounding) {
|
|
80
|
+
val.compounding = cluster.compounding;
|
|
81
|
+
}
|
|
78
82
|
if (!configOnly) {
|
|
79
83
|
val.config_hash = fromHexString(cluster.config_hash);
|
|
80
84
|
}
|
|
@@ -144,7 +144,7 @@ export const verifyDVV1X8 = (clusterLock) => {
|
|
|
144
144
|
// Deposit Data Verification
|
|
145
145
|
for (const element of validator.partial_deposit_data) {
|
|
146
146
|
const depositData = element;
|
|
147
|
-
const { isValidDepositData, depositDataMsg } = verifyDepositData(distributedPublicKey, depositData, clusterLock.cluster_definition.validators[i].withdrawal_address, clusterLock.cluster_definition.fork_version);
|
|
147
|
+
const { isValidDepositData, depositDataMsg } = verifyDepositData(distributedPublicKey, depositData, clusterLock.cluster_definition.validators[i].withdrawal_address, clusterLock.cluster_definition.fork_version, clusterLock.cluster_definition.compounding);
|
|
148
148
|
if (!isValidDepositData) {
|
|
149
149
|
return false;
|
|
150
150
|
}
|