@obolnetwork/obol-sdk 1.0.15 → 1.0.17
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 +6 -3
- package/dist/cjs/package.json +11 -6
- package/dist/cjs/src/ajv.js +27 -0
- package/dist/cjs/src/constants.js +8 -4
- package/dist/cjs/src/index.js +21 -18
- package/dist/cjs/src/schema.js +8 -0
- package/dist/cjs/src/services.js +1 -1
- package/dist/cjs/src/utils.js +3 -3
- package/dist/cjs/src/verification/common.js +19 -7
- package/dist/cjs/src/verification/termsAndConditions.js +1 -1
- package/dist/cjs/src/verification/v1.6.0.js +1 -1
- package/dist/cjs/src/verification/v1.7.0.js +3 -3
- package/dist/cjs/src/verification/v1.8.0.js +3 -3
- package/dist/cjs/test/fixtures.js +71 -82
- package/dist/cjs/test/methods.test.js +54 -27
- package/dist/esm/package.json +11 -6
- package/dist/esm/src/ajv.js +27 -0
- package/dist/esm/src/base.js +1 -1
- package/dist/esm/src/constants.js +7 -3
- package/dist/esm/src/index.js +22 -19
- package/dist/esm/src/schema.js +8 -0
- package/dist/esm/src/services.js +1 -1
- package/dist/esm/src/utils.js +3 -3
- package/dist/esm/src/verification/common.js +27 -15
- package/dist/esm/src/verification/sszTypes.js +1 -1
- package/dist/esm/src/verification/termsAndConditions.js +1 -1
- package/dist/esm/src/verification/v1.6.0.js +5 -5
- package/dist/esm/src/verification/v1.7.0.js +8 -8
- package/dist/esm/src/verification/v1.8.0.js +8 -8
- package/dist/esm/test/fixtures.js +71 -82
- package/dist/esm/test/methods.test.js +55 -28
- package/dist/types/src/constants.d.ts +3 -1
- package/dist/types/src/index.d.ts +11 -9
- package/dist/types/src/schema.d.ts +8 -0
- package/dist/types/src/services.d.ts +1 -1
- package/dist/types/src/types.d.ts +18 -18
- package/package.json +12 -7
- package/src/ajv.ts +38 -7
- package/src/base.ts +22 -18
- package/src/constants.ts +42 -36
- package/src/errors.ts +4 -4
- package/src/index.ts +96 -84
- package/src/schema.ts +10 -2
- package/src/services.ts +7 -7
- package/src/types.ts +65 -65
- package/src/utils.ts +17 -17
- package/src/verification/common.ts +374 -333
- package/src/verification/sszTypes.ts +60 -51
- package/src/verification/termsAndConditions.ts +16 -14
- package/src/verification/v1.6.0.ts +214 -184
- package/src/verification/v1.7.0.ts +268 -233
- package/src/verification/v1.8.0.ts +266 -225
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { ethers } from 'ethers';
|
|
11
11
|
import { Client, validateClusterLock } from '../src/index';
|
|
12
|
-
import { clusterConfigV1X7, clusterLockV1X6, clusterLockV1X7, clusterLockV1X8 } from './fixtures.js';
|
|
12
|
+
import { clusterConfigV1X7, clusterConfigV1X8, clusterLockV1X6, clusterLockV1X7, clusterLockV1X8, } from './fixtures.js';
|
|
13
13
|
import { SDK_VERSION } from '../src/constants';
|
|
14
14
|
import { Base } from '../src/base';
|
|
15
15
|
import { validatePayload } from '../src/ajv';
|
|
@@ -43,51 +43,72 @@ describe('Cluster Client', () => {
|
|
|
43
43
|
clientInstance['request'] = jest
|
|
44
44
|
.fn()
|
|
45
45
|
.mockReturnValue(Promise.resolve({ config_hash: mockConfigHash }));
|
|
46
|
-
const configHash = yield clientInstance.createClusterDefinition(
|
|
46
|
+
const configHash = yield clientInstance.createClusterDefinition(clusterConfigV1X8);
|
|
47
47
|
expect(configHash).toEqual(mockConfigHash);
|
|
48
48
|
}));
|
|
49
49
|
test('acceptClusterDefinition should return cluster definition', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
50
|
clientInstance['request'] = jest
|
|
51
51
|
.fn()
|
|
52
|
-
.mockReturnValue(Promise.resolve(
|
|
52
|
+
.mockReturnValue(Promise.resolve(clusterLockV1X8.cluster_definition));
|
|
53
53
|
const clusterDefinition = yield clientInstance.acceptClusterDefinition({
|
|
54
|
-
enr:
|
|
55
|
-
version:
|
|
56
|
-
},
|
|
57
|
-
expect(clusterDefinition).toEqual(
|
|
54
|
+
enr: clusterLockV1X8.cluster_definition.operators[0].enr,
|
|
55
|
+
version: clusterLockV1X8.cluster_definition.version,
|
|
56
|
+
}, clusterLockV1X8.cluster_definition.config_hash);
|
|
57
|
+
expect(clusterDefinition).toEqual(clusterLockV1X8.cluster_definition);
|
|
58
58
|
}));
|
|
59
59
|
test('createClusterDefinition should throw an error on invalid operators', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
60
|
clientInstance['request'] = jest
|
|
61
61
|
.fn()
|
|
62
62
|
.mockReturnValue(Promise.resolve({ config_hash: mockConfigHash }));
|
|
63
63
|
try {
|
|
64
|
-
yield clientInstance.createClusterDefinition(Object.assign(Object.assign({},
|
|
64
|
+
yield clientInstance.createClusterDefinition(Object.assign(Object.assign({}, clusterConfigV1X8), { operators: [] }));
|
|
65
65
|
}
|
|
66
66
|
catch (error) {
|
|
67
67
|
expect(error.message).toEqual("Schema compilation errors', must NOT have fewer than 4 items");
|
|
68
68
|
}
|
|
69
69
|
}));
|
|
70
|
+
// cause we default to 32000000000
|
|
71
|
+
test('createClusterDefinition should accept a configuration without deposit_amounts', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
72
|
+
clientInstance['request'] = jest
|
|
73
|
+
.fn()
|
|
74
|
+
.mockReturnValue(Promise.resolve({ config_hash: mockConfigHash }));
|
|
75
|
+
const configHash = yield clientInstance.createClusterDefinition(Object.assign({}, clusterConfigV1X7));
|
|
76
|
+
expect(configHash).toEqual(mockConfigHash);
|
|
77
|
+
}));
|
|
78
|
+
test('createClusterDefinition should throw on not valid deposit_amounts ', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
79
|
+
clientInstance['request'] = jest
|
|
80
|
+
.fn()
|
|
81
|
+
.mockReturnValue(Promise.resolve({ config_hash: mockConfigHash }));
|
|
82
|
+
try {
|
|
83
|
+
yield clientInstance.createClusterDefinition(Object.assign(Object.assign({}, clusterConfigV1X7), { deposit_amounts: ['34000000'] }));
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
expect(error.message).toEqual('Schema compilation errors\', must pass "validDepositAmounts" keyword validation');
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
70
89
|
test('validatePayload should throw an error on empty schema', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
90
|
try {
|
|
72
|
-
validatePayload(Object.assign(Object.assign({},
|
|
91
|
+
validatePayload(Object.assign(Object.assign({}, clusterConfigV1X8), { operators: [] }), '');
|
|
73
92
|
}
|
|
74
93
|
catch (error) {
|
|
75
94
|
expect(error.message).toEqual('schema must be object or boolean');
|
|
76
95
|
}
|
|
77
96
|
}));
|
|
78
97
|
test('getClusterdefinition should return cluster definition if config hash exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
|
+
var _c;
|
|
79
99
|
clientInstance['request'] = jest
|
|
80
100
|
.fn()
|
|
81
|
-
.mockReturnValue(Promise.resolve(
|
|
82
|
-
const clusterDefinition = yield clientInstance.getClusterDefinition(
|
|
83
|
-
expect(clusterDefinition.
|
|
101
|
+
.mockReturnValue(Promise.resolve(clusterLockV1X8.cluster_definition));
|
|
102
|
+
const clusterDefinition = yield clientInstance.getClusterDefinition(clusterLockV1X8.cluster_definition.config_hash);
|
|
103
|
+
expect((_c = clusterDefinition.deposit_amounts) === null || _c === void 0 ? void 0 : _c.length).toEqual(clusterLockV1X8.cluster_definition.deposit_amounts.length);
|
|
104
|
+
expect(clusterDefinition.config_hash).toEqual(clusterLockV1X8.cluster_definition.config_hash);
|
|
84
105
|
}));
|
|
85
106
|
test('getClusterLock should return lockFile if exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
86
107
|
clientInstance['request'] = jest
|
|
87
108
|
.fn()
|
|
88
|
-
.mockReturnValue(Promise.resolve(
|
|
89
|
-
const clusterLock = yield clientInstance.getClusterLock(
|
|
90
|
-
expect(clusterLock.lock_hash).toEqual(
|
|
109
|
+
.mockReturnValue(Promise.resolve(clusterLockV1X8));
|
|
110
|
+
const clusterLock = yield clientInstance.getClusterLock(clusterLockV1X8.cluster_definition.config_hash);
|
|
111
|
+
expect(clusterLock.lock_hash).toEqual(clusterLockV1X8.lock_hash);
|
|
91
112
|
}));
|
|
92
113
|
test('request method should set user agent header', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
93
114
|
const server = setupServer(http.get('http://testexample.com/test', ({ request }) => {
|
|
@@ -104,7 +125,9 @@ describe('Cluster Client', () => {
|
|
|
104
125
|
});
|
|
105
126
|
}
|
|
106
127
|
}
|
|
107
|
-
const testBaseInstance = new TestBase({
|
|
128
|
+
const testBaseInstance = new TestBase({
|
|
129
|
+
baseUrl: 'http://testExample.com',
|
|
130
|
+
});
|
|
108
131
|
const result = yield testBaseInstance.callProtectedRequest('/test', {
|
|
109
132
|
method: 'GET',
|
|
110
133
|
});
|
|
@@ -119,7 +142,7 @@ describe('Cluster Client without a signer', () => {
|
|
|
119
142
|
});
|
|
120
143
|
test('createClusterDefinition should throw an error without signer', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
121
144
|
try {
|
|
122
|
-
yield clientInstance.createClusterDefinition(
|
|
145
|
+
yield clientInstance.createClusterDefinition(clusterConfigV1X8);
|
|
123
146
|
}
|
|
124
147
|
catch (err) {
|
|
125
148
|
expect(err.message).toEqual('Signer is required in createClusterDefinition');
|
|
@@ -128,9 +151,9 @@ describe('Cluster Client without a signer', () => {
|
|
|
128
151
|
test('acceptClusterDefinition should throw an error without signer', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
129
152
|
try {
|
|
130
153
|
yield clientInstance.acceptClusterDefinition({
|
|
131
|
-
enr:
|
|
132
|
-
version:
|
|
133
|
-
},
|
|
154
|
+
enr: clusterLockV1X8.cluster_definition.operators[0].enr,
|
|
155
|
+
version: clusterLockV1X8.cluster_definition.version,
|
|
156
|
+
}, clusterLockV1X8.cluster_definition.config_hash);
|
|
134
157
|
}
|
|
135
158
|
catch (err) {
|
|
136
159
|
expect(err.message).toEqual('Signer is required in acceptClusterDefinition');
|
|
@@ -139,23 +162,27 @@ describe('Cluster Client without a signer', () => {
|
|
|
139
162
|
test('getClusterdefinition should return cluster definition if config hash exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
140
163
|
clientInstance['request'] = jest
|
|
141
164
|
.fn()
|
|
142
|
-
.mockReturnValue(Promise.resolve(
|
|
143
|
-
const clusterDefinition = yield clientInstance.getClusterDefinition(
|
|
144
|
-
expect(clusterDefinition.config_hash).toEqual(
|
|
165
|
+
.mockReturnValue(Promise.resolve(clusterLockV1X8.cluster_definition));
|
|
166
|
+
const clusterDefinition = yield clientInstance.getClusterDefinition(clusterLockV1X8.cluster_definition.config_hash);
|
|
167
|
+
expect(clusterDefinition.config_hash).toEqual(clusterLockV1X8.cluster_definition.config_hash);
|
|
145
168
|
}));
|
|
146
169
|
test('getClusterLock should return lockFile if exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
147
170
|
clientInstance['request'] = jest
|
|
148
171
|
.fn()
|
|
149
|
-
.mockReturnValue(Promise.resolve(
|
|
150
|
-
const clusterLock = yield clientInstance.getClusterLock(
|
|
151
|
-
expect(clusterLock.lock_hash).toEqual(
|
|
172
|
+
.mockReturnValue(Promise.resolve(clusterLockV1X8));
|
|
173
|
+
const clusterLock = yield clientInstance.getClusterLock(clusterLockV1X8.cluster_definition.config_hash);
|
|
174
|
+
expect(clusterLock.lock_hash).toEqual(clusterLockV1X8.lock_hash);
|
|
152
175
|
}));
|
|
153
|
-
test.each([
|
|
176
|
+
test.each([
|
|
177
|
+
{ version: 'v1.6.0', clusterLock: clusterLockV1X6 },
|
|
178
|
+
{ version: 'v1.7.0', clusterLock: clusterLockV1X7 },
|
|
179
|
+
{ version: 'v1.8.0', clusterLock: clusterLockV1X8 },
|
|
180
|
+
])("$version: 'should return true on verified cluster lock'", ({ clusterLock }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
154
181
|
const isValidLock = yield validateClusterLock(clusterLock);
|
|
155
182
|
expect(isValidLock).toEqual(true);
|
|
156
183
|
}));
|
|
157
184
|
test('Finds the hash of the latest version of terms and conditions', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
158
185
|
const termsAndConditionsHash = yield hashTermsAndConditions();
|
|
159
|
-
expect(termsAndConditionsHash).toEqual('
|
|
186
|
+
expect(termsAndConditionsHash).toEqual('0xd33721644e8f3afab1495a74abe3523cec12d48b8da6cb760972492ca3f1a273');
|
|
160
187
|
}));
|
|
161
188
|
});
|
|
@@ -68,7 +68,7 @@ export declare const signEnrPayload: (payload: {
|
|
|
68
68
|
enr: string;
|
|
69
69
|
}, chainId: number) => TypedMessage<typeof ENRTypedMessage>;
|
|
70
70
|
export declare const DKG_ALGORITHM = "default";
|
|
71
|
-
export declare const CONFIG_VERSION = "v1.
|
|
71
|
+
export declare const CONFIG_VERSION = "v1.8.0";
|
|
72
72
|
export declare const SDK_VERSION: string;
|
|
73
73
|
export declare const DOMAIN_APPLICATION_BUILDER = "00000001";
|
|
74
74
|
export declare const DOMAIN_DEPOSIT = "03000000";
|
|
@@ -79,7 +79,9 @@ export declare enum DefinitionFlow {
|
|
|
79
79
|
Charon = "Charon-Command"
|
|
80
80
|
}
|
|
81
81
|
export declare const DEFAULT_BASE_URL = "https://api.obol.tech";
|
|
82
|
+
export declare const DEFAULT_BASE_VERSION = "v1";
|
|
82
83
|
export declare const DEFAULT_CHAIN_ID = 17000;
|
|
83
84
|
export declare const ETHER_TO_GWEI: number;
|
|
84
85
|
export declare const TERMS_AND_CONDITIONS_VERSION = 1;
|
|
85
86
|
export declare const TERMS_AND_CONDITIONS_URL: string;
|
|
87
|
+
export declare const TERMS_AND_CONDITIONS_HASH = "0xd33721644e8f3afab1495a74abe3523cec12d48b8da6cb760972492ca3f1a273";
|
|
@@ -23,11 +23,13 @@ export declare class Client extends Base {
|
|
|
23
23
|
chainId?: number;
|
|
24
24
|
}, signer?: Signer);
|
|
25
25
|
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
* Accepts Obol terms and conditions to be able to create or update data.
|
|
27
|
+
* @returns {Promise<string>} terms and conditions acceptance success message.
|
|
28
|
+
* @throws On unverified signature or wrong hash.
|
|
29
|
+
*
|
|
30
|
+
* An example of how to use acceptObolLatestTermsAndConditions:
|
|
31
|
+
* [acceptObolLatestTermsAndConditions](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L44)
|
|
32
|
+
*/
|
|
31
33
|
acceptObolLatestTermsAndConditions(): Promise<string>;
|
|
32
34
|
/**
|
|
33
35
|
* Creates a cluster definition which contains cluster configuration.
|
|
@@ -36,7 +38,7 @@ export declare class Client extends Base {
|
|
|
36
38
|
* @throws On duplicate entries, missing or wrong cluster keys.
|
|
37
39
|
*
|
|
38
40
|
* An example of how to use createClusterDefinition:
|
|
39
|
-
* [createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
|
|
41
|
+
* [createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L59)
|
|
40
42
|
*/
|
|
41
43
|
createClusterDefinition(newCluster: ClusterPayload): Promise<string>;
|
|
42
44
|
/**
|
|
@@ -47,7 +49,7 @@ export declare class Client extends Base {
|
|
|
47
49
|
* @throws On unauthorized, duplicate entries, missing keys, not found cluster or invalid data.
|
|
48
50
|
*
|
|
49
51
|
* An example of how to use acceptClusterDefinition:
|
|
50
|
-
* [acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
|
|
52
|
+
* [acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L106)
|
|
51
53
|
*/
|
|
52
54
|
acceptClusterDefinition(operatorPayload: OperatorPayload, configHash: string): Promise<ClusterDefinition>;
|
|
53
55
|
/**
|
|
@@ -56,7 +58,7 @@ export declare class Client extends Base {
|
|
|
56
58
|
* @throws On not found config hash.
|
|
57
59
|
*
|
|
58
60
|
* An example of how to use getClusterDefinition:
|
|
59
|
-
* [getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
|
|
61
|
+
* [getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L74)
|
|
60
62
|
*/
|
|
61
63
|
getClusterDefinition(configHash: string): Promise<ClusterDefinition>;
|
|
62
64
|
/**
|
|
@@ -65,7 +67,7 @@ export declare class Client extends Base {
|
|
|
65
67
|
* @throws On not found cluster definition or lock.
|
|
66
68
|
*
|
|
67
69
|
* An example of how to use getClusterLock:
|
|
68
|
-
* [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
|
|
70
|
+
* [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L89)
|
|
69
71
|
*/
|
|
70
72
|
getClusterLock(configHash: string): Promise<ClusterLock>;
|
|
71
73
|
}
|
|
@@ -6,6 +6,6 @@ import { type ClusterLock } from './types.js';
|
|
|
6
6
|
* @throws on missing keys or values.
|
|
7
7
|
*
|
|
8
8
|
* An example of how to use validateClusterLock:
|
|
9
|
-
* [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
|
|
9
|
+
* [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127)
|
|
10
10
|
*/
|
|
11
11
|
export declare const validateClusterLock: (lock: ClusterLock) => Promise<boolean>;
|
|
@@ -14,7 +14,7 @@ export declare enum FORK_MAPPING {
|
|
|
14
14
|
/**
|
|
15
15
|
* Node operator data
|
|
16
16
|
*/
|
|
17
|
-
export
|
|
17
|
+
export type ClusterOperator = {
|
|
18
18
|
/** The operator address. */
|
|
19
19
|
address: string;
|
|
20
20
|
/** The operator ethereum node record. */
|
|
@@ -27,7 +27,7 @@ export interface ClusterOperator {
|
|
|
27
27
|
enr_signature?: string;
|
|
28
28
|
/** The operator configuration signature. */
|
|
29
29
|
config_signature?: string;
|
|
30
|
-
}
|
|
30
|
+
};
|
|
31
31
|
/**
|
|
32
32
|
* A partial view of `ClusterOperator` with `enr` and `version` as required properties.
|
|
33
33
|
*/
|
|
@@ -35,25 +35,25 @@ export type OperatorPayload = Partial<ClusterOperator> & Required<Pick<ClusterOp
|
|
|
35
35
|
/**
|
|
36
36
|
* Cluster creator data
|
|
37
37
|
*/
|
|
38
|
-
export
|
|
38
|
+
export type ClusterCreator = {
|
|
39
39
|
/** The creator address. */
|
|
40
40
|
address: string;
|
|
41
41
|
/** The cluster configuration signature. */
|
|
42
42
|
config_signature?: string;
|
|
43
|
-
}
|
|
43
|
+
};
|
|
44
44
|
/**
|
|
45
45
|
* Validator withdrawal configuration
|
|
46
46
|
*/
|
|
47
|
-
export
|
|
47
|
+
export type ClusterValidator = {
|
|
48
48
|
/** The validator fee recipient address. */
|
|
49
49
|
fee_recipient_address: string;
|
|
50
50
|
/** The validator reward address. */
|
|
51
51
|
withdrawal_address: string;
|
|
52
|
-
}
|
|
52
|
+
};
|
|
53
53
|
/**
|
|
54
54
|
* Cluster configuration
|
|
55
55
|
*/
|
|
56
|
-
export
|
|
56
|
+
export type ClusterPayload = {
|
|
57
57
|
/** The cluster name. */
|
|
58
58
|
name: string;
|
|
59
59
|
/** The cluster nodes operators addresses. */
|
|
@@ -62,7 +62,7 @@ export interface ClusterPayload {
|
|
|
62
62
|
validators: ClusterValidator[];
|
|
63
63
|
/** The cluster partial deposits in gwei or 32000000000. */
|
|
64
64
|
deposit_amounts?: string[];
|
|
65
|
-
}
|
|
65
|
+
};
|
|
66
66
|
/**
|
|
67
67
|
* Cluster definition data needed for dkg
|
|
68
68
|
*/
|
|
@@ -93,7 +93,7 @@ export interface ClusterDefinition extends ClusterPayload {
|
|
|
93
93
|
/**
|
|
94
94
|
* Unsigned DV Builder Registration Message
|
|
95
95
|
*/
|
|
96
|
-
export
|
|
96
|
+
export type BuilderRegistrationMessage = {
|
|
97
97
|
/** The DV fee recipient. */
|
|
98
98
|
fee_recipient: string;
|
|
99
99
|
/** Default is 30000000. */
|
|
@@ -102,20 +102,20 @@ export interface BuilderRegistrationMessage {
|
|
|
102
102
|
timestamp: number;
|
|
103
103
|
/** The public key of the DV. */
|
|
104
104
|
pubkey: string;
|
|
105
|
-
}
|
|
105
|
+
};
|
|
106
106
|
/**
|
|
107
107
|
* Pre-generated Signed Validator Builder Registration
|
|
108
108
|
*/
|
|
109
|
-
export
|
|
109
|
+
export type BuilderRegistration = {
|
|
110
110
|
/** Builder registration message. */
|
|
111
111
|
message: BuilderRegistrationMessage;
|
|
112
112
|
/** BLS signature of the builder registration message. */
|
|
113
113
|
signature: string;
|
|
114
|
-
}
|
|
114
|
+
};
|
|
115
115
|
/**
|
|
116
116
|
* Required deposit data for validator activation
|
|
117
117
|
*/
|
|
118
|
-
export
|
|
118
|
+
export type DepositData = {
|
|
119
119
|
/** The public key of the distributed validator. */
|
|
120
120
|
pubkey: string;
|
|
121
121
|
/** The 0x01 withdrawal address of the DV. */
|
|
@@ -126,11 +126,11 @@ export interface DepositData {
|
|
|
126
126
|
deposit_data_root: string;
|
|
127
127
|
/** BLS signature of the deposit message. */
|
|
128
128
|
signature: string;
|
|
129
|
-
}
|
|
129
|
+
};
|
|
130
130
|
/**
|
|
131
131
|
* Required deposit data for validator activation
|
|
132
132
|
*/
|
|
133
|
-
export
|
|
133
|
+
export type DistributedValidator = {
|
|
134
134
|
/** The public key of the distributed validator. */
|
|
135
135
|
distributed_public_key: string;
|
|
136
136
|
/** The public key of the node distributed validator share. */
|
|
@@ -141,11 +141,11 @@ export interface DistributedValidator {
|
|
|
141
141
|
partial_deposit_data?: Array<Partial<DepositData>>;
|
|
142
142
|
/** pre-generated signed validator builder registration to be sent to builder network. */
|
|
143
143
|
builder_registration?: BuilderRegistration;
|
|
144
|
-
}
|
|
144
|
+
};
|
|
145
145
|
/**
|
|
146
146
|
* Cluster Details after DKG is complete
|
|
147
147
|
*/
|
|
148
|
-
export
|
|
148
|
+
export type ClusterLock = {
|
|
149
149
|
/** The cluster definition. */
|
|
150
150
|
cluster_definition: ClusterDefinition;
|
|
151
151
|
/** The cluster distributed validators. */
|
|
@@ -156,4 +156,4 @@ export interface ClusterLock {
|
|
|
156
156
|
lock_hash: string;
|
|
157
157
|
/** Node Signature for the lock hash by the node secp256k1 key. */
|
|
158
158
|
node_signatures?: string[];
|
|
159
|
-
}
|
|
159
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obolnetwork/obol-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
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"
|
|
7
7
|
},
|
|
8
|
-
"homepage": "https://docs.obol.
|
|
8
|
+
"homepage": "https://docs.obol.org/",
|
|
9
9
|
"keywords": [
|
|
10
10
|
"Obol",
|
|
11
11
|
"Distributed Validators",
|
|
@@ -20,13 +20,15 @@
|
|
|
20
20
|
"npm:publish": "npm publish --tag latest",
|
|
21
21
|
"release": "release-it",
|
|
22
22
|
"release:dry": "release-it --dry-run --no-npm",
|
|
23
|
-
"lint": "eslint \"{src,
|
|
24
|
-
"lint-ci": "eslint \"{src,
|
|
23
|
+
"lint": "eslint \"{src,test}/**/*.{js,ts}\" --fix",
|
|
24
|
+
"lint-ci": "eslint \"{src,test}/**/*.{js,ts}\"",
|
|
25
|
+
"prettier-ci": "prettier --check \"{src,test}/**/*.{js,ts}\"",
|
|
26
|
+
"prettier": "prettier --write \"{src,test}/**/*.{js,ts}\""
|
|
25
27
|
},
|
|
26
28
|
"main": "./dist/cjs/src/index.js",
|
|
27
29
|
"module": "./dist/esm/src/index.js",
|
|
28
30
|
"typings": "./dist/types/src/index.d.ts",
|
|
29
|
-
"author": "Obol Labs (https://obol.
|
|
31
|
+
"author": "Obol Labs (https://obol.org)",
|
|
30
32
|
"repository": {
|
|
31
33
|
"type": "git",
|
|
32
34
|
"url": "git+https://github.com/obolnetwork/obol-sdk.git"
|
|
@@ -65,15 +67,18 @@
|
|
|
65
67
|
"@types/semver": "^7.5.8",
|
|
66
68
|
"@types/uuid": "^9.0.1",
|
|
67
69
|
"eslint": "^8.57.0",
|
|
70
|
+
"husky": "^9.0.11",
|
|
68
71
|
"jest": "^28.1.3",
|
|
72
|
+
"lint-staged": "^15.2.2",
|
|
69
73
|
"msw": "^2.2.1",
|
|
70
74
|
"npm-run-all": "^4.1.5",
|
|
75
|
+
"prettier": "^3.2.5",
|
|
71
76
|
"release-it": "^17.2.1",
|
|
72
77
|
"ts-jest": "^28.0.8",
|
|
73
78
|
"tsup": "^6.7.0",
|
|
74
79
|
"typedoc": "^0.25.7",
|
|
75
80
|
"typedoc-plugin-markdown": "^4.0.0-next.50",
|
|
76
|
-
"typescript": "
|
|
81
|
+
"typescript": "~5.3.3"
|
|
77
82
|
},
|
|
78
83
|
"engines": {
|
|
79
84
|
"node": ">= 16"
|
|
@@ -128,4 +133,4 @@
|
|
|
128
133
|
".ts"
|
|
129
134
|
]
|
|
130
135
|
}
|
|
131
|
-
}
|
|
136
|
+
}
|
package/src/ajv.ts
CHANGED
|
@@ -1,16 +1,47 @@
|
|
|
1
|
-
import Ajv, { type ErrorObject } from 'ajv'
|
|
1
|
+
import Ajv, { type ErrorObject } from 'ajv';
|
|
2
|
+
import { parseUnits } from 'ethers';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
function validDepositAmounts(data: boolean, deposits: string[]): boolean {
|
|
5
|
+
let sum = 0;
|
|
6
|
+
// from ether togwei is same as from gwei to wei
|
|
7
|
+
const maxDeposit = Number(parseUnits('32', 'gwei'));
|
|
8
|
+
const minDeposit = Number(parseUnits('1', 'gwei'));
|
|
9
|
+
|
|
10
|
+
for (const element of deposits) {
|
|
11
|
+
const amountInGWei = Number(element);
|
|
12
|
+
|
|
13
|
+
if (
|
|
14
|
+
!Number.isInteger(amountInGWei) ||
|
|
15
|
+
amountInGWei > maxDeposit ||
|
|
16
|
+
amountInGWei < minDeposit
|
|
17
|
+
) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
sum += amountInGWei;
|
|
21
|
+
}
|
|
22
|
+
if (sum / minDeposit !== 32) {
|
|
23
|
+
return false;
|
|
24
|
+
} else {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function validatePayload(
|
|
4
30
|
data: any,
|
|
5
31
|
schema: any,
|
|
6
32
|
): ErrorObject[] | undefined | null | boolean {
|
|
7
|
-
const ajv = new Ajv()
|
|
8
|
-
|
|
9
|
-
|
|
33
|
+
const ajv = new Ajv();
|
|
34
|
+
ajv.addKeyword({
|
|
35
|
+
keyword: 'validDepositAmounts',
|
|
36
|
+
validate: validDepositAmounts,
|
|
37
|
+
errors: true,
|
|
38
|
+
});
|
|
39
|
+
const validate = ajv.compile(schema);
|
|
40
|
+
const isValid = validate(data);
|
|
10
41
|
if (!isValid) {
|
|
11
42
|
throw new Error(
|
|
12
43
|
`Schema compilation errors', ${validate.errors?.[0].message}`,
|
|
13
|
-
)
|
|
44
|
+
);
|
|
14
45
|
}
|
|
15
|
-
return isValid
|
|
46
|
+
return isValid;
|
|
16
47
|
}
|
package/src/base.ts
CHANGED
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
// src/resources/base.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_BASE_URL,
|
|
4
|
+
DEFAULT_CHAIN_ID,
|
|
5
|
+
SDK_VERSION,
|
|
6
|
+
} from './constants.js';
|
|
7
|
+
import { FORK_MAPPING } from './types.js';
|
|
4
8
|
|
|
5
9
|
interface Config {
|
|
6
|
-
baseUrl?: string
|
|
7
|
-
chainId?: FORK_MAPPING
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
chainId?: FORK_MAPPING;
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
export abstract class Base {
|
|
11
|
-
baseUrl: string
|
|
12
|
-
chainId: number
|
|
13
|
-
fork_version: string
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
chainId: number;
|
|
17
|
+
fork_version: string;
|
|
14
18
|
|
|
15
|
-
constructor
|
|
19
|
+
constructor({
|
|
16
20
|
baseUrl = DEFAULT_BASE_URL,
|
|
17
21
|
chainId = DEFAULT_CHAIN_ID,
|
|
18
22
|
}: Config) {
|
|
19
|
-
this.baseUrl = baseUrl
|
|
20
|
-
this.chainId = chainId
|
|
21
|
-
this.fork_version = FORK_MAPPING[this.chainId]
|
|
23
|
+
this.baseUrl = baseUrl;
|
|
24
|
+
this.chainId = chainId;
|
|
25
|
+
this.fork_version = FORK_MAPPING[this.chainId];
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
protected async request<T>(
|
|
25
29
|
endpoint: string,
|
|
26
30
|
options?: RequestInit,
|
|
27
31
|
): Promise<T> {
|
|
28
|
-
const url = `${this.baseUrl}${endpoint}
|
|
32
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
29
33
|
const config = {
|
|
30
34
|
...options,
|
|
31
35
|
headers: {
|
|
@@ -33,18 +37,18 @@ export abstract class Base {
|
|
|
33
37
|
'User-Agent': `Obol-SDK/${SDK_VERSION}`,
|
|
34
38
|
...options?.headers,
|
|
35
39
|
},
|
|
36
|
-
}
|
|
40
|
+
};
|
|
37
41
|
|
|
38
42
|
try {
|
|
39
|
-
const response = await fetch(url, config)
|
|
43
|
+
const response = await fetch(url, config);
|
|
40
44
|
if (response.ok) {
|
|
41
|
-
return await response.json()
|
|
45
|
+
return await response.json();
|
|
42
46
|
} else {
|
|
43
|
-
const errorResponse = await response.json()
|
|
44
|
-
throw errorResponse
|
|
47
|
+
const errorResponse = await response.json();
|
|
48
|
+
throw errorResponse;
|
|
45
49
|
}
|
|
46
50
|
} catch (e: any) {
|
|
47
|
-
throw e
|
|
51
|
+
throw e;
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
}
|