@obolnetwork/obol-sdk 2.4.4 → 2.4.6
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 +1 -1
- package/dist/cjs/package.json +6 -5
- package/dist/cjs/src/incentiveHelpers.js +2 -4
- package/dist/cjs/src/incentives.js +26 -5
- package/dist/cjs/src/index.js +3 -1
- package/dist/cjs/src/services.js +3 -2
- package/dist/cjs/src/types.js +0 -9
- package/dist/cjs/src/utils.js +4 -4
- package/dist/cjs/src/verification/common.js +12 -9
- package/dist/cjs/src/verification/signature-validator.js +6 -5
- package/dist/cjs/test/incentives.test.js +4 -4
- package/dist/cjs/test/methods.test.js +11 -0
- package/dist/esm/package.json +6 -5
- package/dist/esm/src/incentiveHelpers.js +3 -5
- package/dist/esm/src/incentives.js +26 -5
- package/dist/esm/src/index.js +2 -1
- package/dist/esm/src/services.js +3 -2
- package/dist/esm/src/splitHelpers.js +1 -1
- package/dist/esm/src/types.js +0 -9
- package/dist/esm/src/utils.js +4 -4
- package/dist/esm/src/verification/common.js +12 -9
- package/dist/esm/src/verification/signature-validator.js +6 -5
- package/dist/esm/test/incentives.test.js +4 -4
- package/dist/esm/test/methods.test.js +11 -0
- package/dist/types/src/incentiveHelpers.d.ts +3 -4
- package/dist/types/src/incentives.d.ts +29 -13
- package/dist/types/src/index.d.ts +15 -4
- package/dist/types/src/services.d.ts +3 -2
- package/dist/types/src/splitHelpers.d.ts +7 -8
- package/dist/types/src/types.d.ts +21 -5
- package/dist/types/src/utils.d.ts +5 -5
- package/dist/types/src/verification/common.d.ts +2 -2
- package/dist/types/src/verification/signature-validator.d.ts +5 -2
- package/package.json +6 -5
- package/src/incentiveHelpers.ts +5 -15
- package/src/incentives.ts +37 -33
- package/src/index.ts +27 -23
- package/src/services.ts +4 -2
- package/src/splitHelpers.ts +9 -14
- package/src/types.ts +37 -17
- package/src/utils.ts +11 -8
- package/src/verification/common.ts +13 -1
- package/src/verification/signature-validator.ts +10 -3
|
@@ -100,7 +100,7 @@ export const clusterLockHash = (clusterLock) => {
|
|
|
100
100
|
};
|
|
101
101
|
// Lock verification
|
|
102
102
|
// cluster-definition signatures verification
|
|
103
|
-
const validatePOSTConfigHashSigner = (address, signature, configHash, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
103
|
+
const validatePOSTConfigHashSigner = (address, signature, configHash, chainId, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
104
104
|
try {
|
|
105
105
|
const data = signCreatorConfigHashPayload({ creator_config_hash: configHash }, chainId);
|
|
106
106
|
return yield validateAddressSignature({
|
|
@@ -108,13 +108,14 @@ const validatePOSTConfigHashSigner = (address, signature, configHash, chainId) =
|
|
|
108
108
|
token: signature,
|
|
109
109
|
data,
|
|
110
110
|
chainId,
|
|
111
|
+
safeRpcUrl,
|
|
111
112
|
});
|
|
112
113
|
}
|
|
113
114
|
catch (err) {
|
|
114
115
|
throw err;
|
|
115
116
|
}
|
|
116
117
|
});
|
|
117
|
-
const validatePUTConfigHashSigner = (address, signature, configHash, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
118
|
+
const validatePUTConfigHashSigner = (address, signature, configHash, chainId, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
118
119
|
try {
|
|
119
120
|
const data = signOperatorConfigHashPayload({ operator_config_hash: configHash }, chainId);
|
|
120
121
|
return yield validateAddressSignature({
|
|
@@ -122,13 +123,14 @@ const validatePUTConfigHashSigner = (address, signature, configHash, chainId) =>
|
|
|
122
123
|
token: signature,
|
|
123
124
|
data,
|
|
124
125
|
chainId,
|
|
126
|
+
safeRpcUrl,
|
|
125
127
|
});
|
|
126
128
|
}
|
|
127
129
|
catch (err) {
|
|
128
130
|
throw err;
|
|
129
131
|
}
|
|
130
132
|
});
|
|
131
|
-
const validateEnrSigner = (address, signature, payload, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
133
|
+
const validateEnrSigner = (address, signature, payload, chainId, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
132
134
|
try {
|
|
133
135
|
const data = signEnrPayload({ enr: payload }, chainId);
|
|
134
136
|
return yield validateAddressSignature({
|
|
@@ -136,18 +138,19 @@ const validateEnrSigner = (address, signature, payload, chainId) => __awaiter(vo
|
|
|
136
138
|
token: signature,
|
|
137
139
|
data,
|
|
138
140
|
chainId,
|
|
141
|
+
safeRpcUrl,
|
|
139
142
|
});
|
|
140
143
|
}
|
|
141
144
|
catch (err) {
|
|
142
145
|
throw err;
|
|
143
146
|
}
|
|
144
147
|
});
|
|
145
|
-
const verifyDefinitionSignatures = (clusterDefinition, definitionType) => __awaiter(void 0, void 0, void 0, function* () {
|
|
148
|
+
const verifyDefinitionSignatures = (clusterDefinition, definitionType, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
146
149
|
if (definitionType === DefinitionFlow.Charon) {
|
|
147
150
|
return true;
|
|
148
151
|
}
|
|
149
152
|
else {
|
|
150
|
-
const isPOSTConfigHashSignerValid = yield validatePOSTConfigHashSigner(clusterDefinition.creator.address, clusterDefinition.creator.config_signature, clusterDefinition.config_hash, FORK_MAPPING[clusterDefinition.fork_version]);
|
|
153
|
+
const isPOSTConfigHashSignerValid = yield validatePOSTConfigHashSigner(clusterDefinition.creator.address, clusterDefinition.creator.config_signature, clusterDefinition.config_hash, FORK_MAPPING[clusterDefinition.fork_version], safeRpcUrl);
|
|
151
154
|
if (!isPOSTConfigHashSignerValid) {
|
|
152
155
|
return false;
|
|
153
156
|
}
|
|
@@ -155,8 +158,8 @@ const verifyDefinitionSignatures = (clusterDefinition, definitionType) => __awai
|
|
|
155
158
|
return true;
|
|
156
159
|
}
|
|
157
160
|
for (const operator of clusterDefinition.operators) {
|
|
158
|
-
const isPUTConfigHashSignerValid = yield validatePUTConfigHashSigner(operator.address, operator.config_signature, clusterDefinition.config_hash, FORK_MAPPING[clusterDefinition.fork_version]);
|
|
159
|
-
const isENRSignerValid = yield validateEnrSigner(operator.address, operator.enr_signature, operator.enr, FORK_MAPPING[clusterDefinition.fork_version]);
|
|
161
|
+
const isPUTConfigHashSignerValid = yield validatePUTConfigHashSigner(operator.address, operator.config_signature, clusterDefinition.config_hash, FORK_MAPPING[clusterDefinition.fork_version], safeRpcUrl);
|
|
162
|
+
const isENRSignerValid = yield validateEnrSigner(operator.address, operator.enr_signature, operator.enr, FORK_MAPPING[clusterDefinition.fork_version], safeRpcUrl);
|
|
160
163
|
if (!isPUTConfigHashSignerValid || !isENRSignerValid) {
|
|
161
164
|
return false;
|
|
162
165
|
}
|
|
@@ -287,13 +290,13 @@ const verifyLockData = (clusterLock) => __awaiter(void 0, void 0, void 0, functi
|
|
|
287
290
|
}
|
|
288
291
|
return false;
|
|
289
292
|
});
|
|
290
|
-
export const isValidClusterLock = (clusterLock) => __awaiter(void 0, void 0, void 0, function* () {
|
|
293
|
+
export const isValidClusterLock = (clusterLock, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
291
294
|
try {
|
|
292
295
|
const definitionType = definitionFlow(clusterLock.cluster_definition);
|
|
293
296
|
if (definitionType == null) {
|
|
294
297
|
return false;
|
|
295
298
|
}
|
|
296
|
-
const isValidDefinitionData = yield verifyDefinitionSignatures(clusterLock.cluster_definition, definitionType);
|
|
299
|
+
const isValidDefinitionData = yield verifyDefinitionSignatures(clusterLock.cluster_definition, definitionType, safeRpcUrl);
|
|
297
300
|
if (!isValidDefinitionData) {
|
|
298
301
|
return false;
|
|
299
302
|
}
|
|
@@ -14,9 +14,9 @@ import Safe from '@safe-global/protocol-kit';
|
|
|
14
14
|
import { PROVIDER_MAP } from '../constants';
|
|
15
15
|
import { hashTypedData } from '@safe-global/protocol-kit/dist/src/utils';
|
|
16
16
|
import { isContractAvailable, getProvider } from '../utils';
|
|
17
|
-
export const validateAddressSignature = ({ address, token, data, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
export const validateAddressSignature = ({ address, token, data, chainId, safeRpcUrl, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
18
18
|
try {
|
|
19
|
-
const provider = getProvider(chainId);
|
|
19
|
+
const provider = getProvider(chainId, safeRpcUrl);
|
|
20
20
|
if (provider) {
|
|
21
21
|
const contractAddress = yield isContractAvailable(address, provider);
|
|
22
22
|
if (contractAddress) {
|
|
@@ -25,6 +25,7 @@ export const validateAddressSignature = ({ address, token, data, chainId, }) =>
|
|
|
25
25
|
data: data,
|
|
26
26
|
address,
|
|
27
27
|
chainId,
|
|
28
|
+
safeRpcUrl,
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
31
|
}
|
|
@@ -46,11 +47,11 @@ export const validateEOASignature = ({ token, data, address, }) => {
|
|
|
46
47
|
throw err;
|
|
47
48
|
}
|
|
48
49
|
};
|
|
49
|
-
export const validateSmartContractSignature = ({ token, data, address, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
|
+
export const validateSmartContractSignature = ({ token, data, address, chainId, safeRpcUrl, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
51
|
try {
|
|
51
|
-
const
|
|
52
|
+
const safeProvider = safeRpcUrl !== null && safeRpcUrl !== void 0 ? safeRpcUrl : PROVIDER_MAP[chainId];
|
|
52
53
|
const protocolKit = yield Safe.init({
|
|
53
|
-
provider,
|
|
54
|
+
provider: safeProvider,
|
|
54
55
|
safeAddress: address,
|
|
55
56
|
});
|
|
56
57
|
const messageHash = hashTypedData(data);
|
|
@@ -79,13 +79,13 @@ describe('Client.incentives', () => {
|
|
|
79
79
|
merkleProof: mockIncentivesData.merkle_proof,
|
|
80
80
|
});
|
|
81
81
|
}));
|
|
82
|
-
test('claimIncentives should return
|
|
82
|
+
test('claimIncentives should return txHash as null when incentives are already claimed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
83
83
|
jest
|
|
84
84
|
.spyOn(clientInstance.incentives, 'getIncentivesByAddress')
|
|
85
85
|
.mockResolvedValue(mockIncentivesData);
|
|
86
86
|
jest.spyOn(clientInstance.incentives, 'isClaimed').mockResolvedValue(true);
|
|
87
87
|
const result = yield clientInstance.incentives.claimIncentives(mockIncentivesData.operator_address);
|
|
88
|
-
expect(result).toEqual({
|
|
88
|
+
expect(result).toEqual({ txHash: null });
|
|
89
89
|
expect(incentivesHelpers.claimIncentivesFromMerkleDistributor).not.toHaveBeenCalled();
|
|
90
90
|
}));
|
|
91
91
|
test('claimIncentives should throw an error if no incentives found for address', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -120,7 +120,7 @@ describe('Client.incentives', () => {
|
|
|
120
120
|
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
|
|
121
121
|
const result = yield clientInstance.incentives.isClaimed(mockIncentivesData.contract_address, mockIncentivesData.index);
|
|
122
122
|
expect(result).toBe(true);
|
|
123
|
-
expect(incentivesHelpers.isClaimedFromMerkleDistributor).toHaveBeenCalledWith(
|
|
123
|
+
expect(incentivesHelpers.isClaimedFromMerkleDistributor).toHaveBeenCalledWith(mockIncentivesData.contract_address, mockIncentivesData.index, {});
|
|
124
124
|
}));
|
|
125
125
|
test('isClaimed should return false when incentive is not claimed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
126
126
|
jest
|
|
@@ -147,7 +147,7 @@ describe('Client.incentives', () => {
|
|
|
147
147
|
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
|
|
148
148
|
const result = yield clientWithoutSigner.incentives.isClaimed(mockIncentivesData.contract_address, mockIncentivesData.index);
|
|
149
149
|
expect(result).toBe(true);
|
|
150
|
-
expect(incentivesHelpers.isClaimedFromMerkleDistributor).toHaveBeenCalledWith(
|
|
150
|
+
expect(incentivesHelpers.isClaimedFromMerkleDistributor).toHaveBeenCalledWith(mockIncentivesData.contract_address, mockIncentivesData.index, provider);
|
|
151
151
|
}));
|
|
152
152
|
test('getIncentivesByAddress should make the correct API request', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
153
153
|
const mockAddress = '0x1234567890abcdef1234567890abcdef12345678';
|
|
@@ -140,6 +140,9 @@ describe('Cluster Client without a signer', () => {
|
|
|
140
140
|
beforeAll(() => {
|
|
141
141
|
jest.restoreAllMocks();
|
|
142
142
|
});
|
|
143
|
+
beforeEach(() => {
|
|
144
|
+
jest.resetModules();
|
|
145
|
+
});
|
|
143
146
|
test('createClusterDefinition should throw an error without signer', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
144
147
|
try {
|
|
145
148
|
yield clientInstance.createClusterDefinition(clusterConfigV1X8);
|
|
@@ -194,6 +197,14 @@ describe('Cluster Client without a signer', () => {
|
|
|
194
197
|
const isValidLock = yield validateClusterLock(clusterLock);
|
|
195
198
|
expect(isValidLock).toEqual(true);
|
|
196
199
|
}));
|
|
200
|
+
test('should return true on verified cluster lock with Safe wallet and safe rpc url', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
201
|
+
process.env.RPC_HOLESKY = undefined;
|
|
202
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
203
|
+
const { validateClusterLock: validateLockWithRpcUrl, } = require('../src/index');
|
|
204
|
+
const safeRpcUrl = 'https://ethereum-holesky-rpc.publicnode.com';
|
|
205
|
+
const isValidLock = yield validateLockWithRpcUrl(clusterLockWithSafe, safeRpcUrl);
|
|
206
|
+
expect(isValidLock).toEqual(true);
|
|
207
|
+
}));
|
|
197
208
|
test('validateCluster should return false for cluster with null deposit_amounts and incorrect partial_deposits', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
198
209
|
const partialDeposit = nullDepositAmountsClusterLockV1X8.distributed_validators[0]
|
|
199
210
|
.partial_deposit_data[0];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { type ETH_ADDRESS } from './types';
|
|
2
|
-
import { type JsonRpcApiProvider, type JsonRpcProvider, type Provider, type Signer } from 'ethers';
|
|
1
|
+
import { type ProviderType, type SignerType, type ETH_ADDRESS } from './types';
|
|
3
2
|
export declare const claimIncentivesFromMerkleDistributor: (incentivesData: {
|
|
4
|
-
signer:
|
|
3
|
+
signer: SignerType;
|
|
5
4
|
contractAddress: ETH_ADDRESS;
|
|
6
5
|
index: number;
|
|
7
6
|
operatorAddress: ETH_ADDRESS;
|
|
@@ -10,4 +9,4 @@ export declare const claimIncentivesFromMerkleDistributor: (incentivesData: {
|
|
|
10
9
|
}) => Promise<{
|
|
11
10
|
txHash: string;
|
|
12
11
|
}>;
|
|
13
|
-
export declare const isClaimedFromMerkleDistributor: (
|
|
12
|
+
export declare const isClaimedFromMerkleDistributor: (contractAddress: ETH_ADDRESS, index: number, provider: ProviderType | undefined | null) => Promise<boolean>;
|
|
@@ -1,28 +1,38 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type ClaimableIncentives, type ETH_ADDRESS, type ProviderType, type SignerType, type ClaimIncentivesResponse } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Incentives can be used for fetching and claiming Obol incentives.
|
|
4
|
+
* @class
|
|
5
|
+
* @internal Access it through Client.incentives.
|
|
6
|
+
* @example
|
|
7
|
+
* const obolClient = new Client(config);
|
|
8
|
+
* await obolClient.incentives.claimIncentives(address);
|
|
9
|
+
*/
|
|
3
10
|
export declare class Incentives {
|
|
4
11
|
private readonly signer;
|
|
5
12
|
readonly chainId: number;
|
|
6
13
|
private readonly request;
|
|
7
|
-
readonly provider:
|
|
8
|
-
constructor(signer:
|
|
14
|
+
readonly provider: ProviderType | undefined | null;
|
|
15
|
+
constructor(signer: SignerType | undefined, chainId: number, request: (endpoint: string, options?: RequestInit) => Promise<any>, provider: ProviderType | undefined | null);
|
|
9
16
|
/**
|
|
10
|
-
* Claims
|
|
11
|
-
*
|
|
17
|
+
* Claims Obol incentives from a Merkle Distributor contract using an address.
|
|
18
|
+
*
|
|
19
|
+
* This method automatically fetches incentive data and verifies whether the incentives have already been claimed.
|
|
20
|
+
* If `txHash` is `null`, it indicates that the incentives were already claimed.
|
|
21
|
+
*
|
|
22
|
+
* Note: This method is not yet enabled and will throw an error if called.
|
|
12
23
|
*
|
|
13
24
|
* @remarks
|
|
14
25
|
* **⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed
|
|
15
26
|
* and not pushed to version control.
|
|
16
27
|
*
|
|
17
28
|
* @param {string} address - The address to claim incentives for
|
|
18
|
-
* @returns {Promise<
|
|
29
|
+
* @returns {Promise<ClaimIncentivesResponse>} The transaction hash or already claimed status
|
|
19
30
|
* @throws Will throw an error if the incentives data is not found or the claim fails
|
|
31
|
+
*
|
|
32
|
+
* An example of how to use claimIncentives:
|
|
33
|
+
* [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L281)
|
|
20
34
|
*/
|
|
21
|
-
claimIncentives(address: string): Promise<
|
|
22
|
-
txHash: string;
|
|
23
|
-
} | {
|
|
24
|
-
alreadyClaimed: true;
|
|
25
|
-
}>;
|
|
35
|
+
claimIncentives(address: string): Promise<ClaimIncentivesResponse>;
|
|
26
36
|
/**
|
|
27
37
|
* Read isClaimed.
|
|
28
38
|
*
|
|
@@ -30,12 +40,18 @@ export declare class Incentives {
|
|
|
30
40
|
* @param {ETH_ADDRESS} index - operator index in merkle tree
|
|
31
41
|
* @returns {Promise<boolean>} true if incentives are already claime
|
|
32
42
|
*
|
|
43
|
+
*
|
|
44
|
+
* An example of how to use isClaimed:
|
|
45
|
+
* [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L266)
|
|
33
46
|
*/
|
|
34
47
|
isClaimed(contractAddress: ETH_ADDRESS, index: number): Promise<boolean>;
|
|
35
48
|
/**
|
|
36
49
|
* @param address - Operator address
|
|
37
50
|
* @returns {Promise<IncentivesType>} The matched incentives from DB
|
|
38
51
|
* @throws On not found if address not found.
|
|
52
|
+
*
|
|
53
|
+
* An example of how to use getIncentivesByAddress:
|
|
54
|
+
* [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L250)
|
|
39
55
|
*/
|
|
40
|
-
getIncentivesByAddress(address: string): Promise<
|
|
56
|
+
getIncentivesByAddress(address: string): Promise<ClaimableIncentives>;
|
|
41
57
|
}
|
|
@@ -1,18 +1,29 @@
|
|
|
1
|
-
import { type Provider, type Signer, type JsonRpcSigner, type JsonRpcProvider, type JsonRpcApiProvider } from 'ethers';
|
|
2
1
|
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';
|
|
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';
|
|
4
3
|
import { Incentives } from './incentives.js';
|
|
5
4
|
export * from './types.js';
|
|
6
5
|
export * from './services.js';
|
|
7
6
|
export * from './verification/signature-validator.js';
|
|
8
7
|
export * from './verification/common.js';
|
|
8
|
+
export { Incentives } from './incentives.js';
|
|
9
9
|
/**
|
|
10
10
|
* Obol sdk Client can be used for creating, managing and activating distributed validators.
|
|
11
11
|
*/
|
|
12
12
|
export declare class Client extends Base {
|
|
13
|
+
/**
|
|
14
|
+
* The signer used for signing transactions.
|
|
15
|
+
*/
|
|
13
16
|
private readonly signer;
|
|
17
|
+
/**
|
|
18
|
+
* The incentives module, responsible for managing Obol tokens distribution.
|
|
19
|
+
* @type {Incentives}
|
|
20
|
+
*/
|
|
14
21
|
incentives: Incentives;
|
|
15
|
-
|
|
22
|
+
/**
|
|
23
|
+
* The blockchain provider, used to interact with the network.
|
|
24
|
+
* It can be null, undefined, or a valid provider instance and defaults to the Signer provider if Signer is passed.
|
|
25
|
+
*/
|
|
26
|
+
provider: ProviderType | undefined | null;
|
|
16
27
|
/**
|
|
17
28
|
* @param config - Client configurations
|
|
18
29
|
* @param config.baseUrl - obol-api url
|
|
@@ -26,7 +37,7 @@ export declare class Client extends Base {
|
|
|
26
37
|
constructor(config: {
|
|
27
38
|
baseUrl?: string;
|
|
28
39
|
chainId?: number;
|
|
29
|
-
}, signer?:
|
|
40
|
+
}, signer?: SignerType, provider?: ProviderType);
|
|
30
41
|
/**
|
|
31
42
|
* Accepts Obol terms and conditions to be able to create or update data.
|
|
32
43
|
* @returns {Promise<string>} terms and conditions acceptance success message.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { type ClusterLock } from './types.js';
|
|
1
|
+
import { type SafeRpcUrl, type ClusterLock } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Verifies Cluster Lock's validity.
|
|
4
4
|
* @param lock - cluster lock
|
|
5
|
+
* @param safeRpcUrl - optional safeRpcUrl for safe wallet verification
|
|
5
6
|
* @returns {Promise<{ result: boolean }> } boolean result to indicate if lock is valid
|
|
6
7
|
* @throws on missing keys or values.
|
|
7
8
|
*
|
|
8
9
|
* An example of how to use validateClusterLock:
|
|
9
10
|
* [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127)
|
|
10
11
|
*/
|
|
11
|
-
export declare const validateClusterLock: (lock: ClusterLock) => Promise<boolean>;
|
|
12
|
+
export declare const validateClusterLock: (lock: ClusterLock, safeRpcUrl?: SafeRpcUrl) => Promise<boolean>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { type OWRTranches, type ClusterValidator, type ETH_ADDRESS, type SplitRecipient } from './types';
|
|
2
|
-
import { type Signer } from 'ethers';
|
|
1
|
+
import { type OWRTranches, type ClusterValidator, type ETH_ADDRESS, type SplitRecipient, type SignerType } from './types';
|
|
3
2
|
type Call = {
|
|
4
3
|
target: ETH_ADDRESS;
|
|
5
4
|
callData: string;
|
|
@@ -21,7 +20,7 @@ export declare const formatSplitRecipients: (recipients: SplitRecipient[]) => {
|
|
|
21
20
|
percentAllocations: number[];
|
|
22
21
|
};
|
|
23
22
|
export declare const predictSplitterAddress: ({ signer, accounts, percentAllocations, chainId, distributorFee, controllerAddress, }: {
|
|
24
|
-
signer:
|
|
23
|
+
signer: SignerType;
|
|
25
24
|
accounts: ETH_ADDRESS[];
|
|
26
25
|
percentAllocations: number[];
|
|
27
26
|
chainId: number;
|
|
@@ -29,7 +28,7 @@ export declare const predictSplitterAddress: ({ signer, accounts, percentAllocat
|
|
|
29
28
|
controllerAddress: ETH_ADDRESS;
|
|
30
29
|
}) => Promise<ETH_ADDRESS>;
|
|
31
30
|
export declare const handleDeployOWRAndSplitter: ({ signer, isSplitterDeployed, predictedSplitterAddress, accounts, percentAllocations, etherAmount, principalRecipient, chainId, distributorFee, controllerAddress, recoveryAddress, }: {
|
|
32
|
-
signer:
|
|
31
|
+
signer: SignerType;
|
|
33
32
|
isSplitterDeployed: boolean;
|
|
34
33
|
predictedSplitterAddress: ETH_ADDRESS;
|
|
35
34
|
accounts: ETH_ADDRESS[];
|
|
@@ -42,7 +41,7 @@ export declare const handleDeployOWRAndSplitter: ({ signer, isSplitterDeployed,
|
|
|
42
41
|
recoveryAddress: ETH_ADDRESS;
|
|
43
42
|
}) => Promise<ClusterValidator>;
|
|
44
43
|
export declare const deploySplitterContract: ({ signer, accounts, percentAllocations, chainId, distributorFee, controllerAddress, }: {
|
|
45
|
-
signer:
|
|
44
|
+
signer: SignerType;
|
|
46
45
|
accounts: ETH_ADDRESS[];
|
|
47
46
|
percentAllocations: number[];
|
|
48
47
|
chainId: number;
|
|
@@ -52,7 +51,7 @@ export declare const deploySplitterContract: ({ signer, accounts, percentAllocat
|
|
|
52
51
|
export declare const deploySplitterAndOWRContracts: ({ owrArgs, splitterArgs, signer, chainId, }: {
|
|
53
52
|
owrArgs: OWRArgs;
|
|
54
53
|
splitterArgs: SplitArgs;
|
|
55
|
-
signer:
|
|
54
|
+
signer: SignerType;
|
|
56
55
|
chainId: number;
|
|
57
56
|
}) => Promise<{
|
|
58
57
|
owrAddress: ETH_ADDRESS;
|
|
@@ -60,7 +59,7 @@ export declare const deploySplitterAndOWRContracts: ({ owrArgs, splitterArgs, si
|
|
|
60
59
|
}>;
|
|
61
60
|
export declare const getOWRTranches: ({ owrAddress, signer, }: {
|
|
62
61
|
owrAddress: ETH_ADDRESS;
|
|
63
|
-
signer:
|
|
62
|
+
signer: SignerType;
|
|
64
63
|
}) => Promise<OWRTranches>;
|
|
65
|
-
export declare const multicall: (calls: Call[], signer:
|
|
64
|
+
export declare const multicall: (calls: Call[], signer: SignerType, multicallAddress: string) => Promise<any>;
|
|
66
65
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Wallet, type ethers, type JsonRpcApiProvider, type JsonRpcProvider, type JsonRpcSigner, type Provider, type Signer } from 'ethers';
|
|
1
2
|
/**
|
|
2
3
|
* Permitted ChainID's
|
|
3
4
|
*/
|
|
@@ -15,9 +16,6 @@ export declare enum FORK_MAPPING {
|
|
|
15
16
|
/** Hoodi Chain. */
|
|
16
17
|
'0x10000910' = 560048
|
|
17
18
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Permitted Chain Names
|
|
20
|
-
*/
|
|
21
19
|
export declare const FORK_NAMES: Record<number, string>;
|
|
22
20
|
/**
|
|
23
21
|
* Node operator data
|
|
@@ -214,9 +212,9 @@ export type ClusterLock = {
|
|
|
214
212
|
node_signatures?: string[];
|
|
215
213
|
};
|
|
216
214
|
/**
|
|
217
|
-
* Incentives
|
|
215
|
+
* Claimable Obol Incentives
|
|
218
216
|
*/
|
|
219
|
-
export type
|
|
217
|
+
export type ClaimableIncentives = {
|
|
220
218
|
/** Operator Address. */
|
|
221
219
|
operator_address: string;
|
|
222
220
|
/** The amount the recipient is entitled to. */
|
|
@@ -232,3 +230,21 @@ export type Incentives = {
|
|
|
232
230
|
* String expected to be Ethereum Address
|
|
233
231
|
*/
|
|
234
232
|
export type ETH_ADDRESS = string;
|
|
233
|
+
/**
|
|
234
|
+
* Provider Types
|
|
235
|
+
*/
|
|
236
|
+
export type ProviderType = Provider | JsonRpcProvider | JsonRpcApiProvider | ethers.BrowserProvider;
|
|
237
|
+
/**
|
|
238
|
+
* Safe Wallet Provider Types
|
|
239
|
+
*/
|
|
240
|
+
export type SafeRpcUrl = string;
|
|
241
|
+
/**
|
|
242
|
+
* Signer Types
|
|
243
|
+
*/
|
|
244
|
+
export type SignerType = Signer | JsonRpcSigner | Wallet;
|
|
245
|
+
/**
|
|
246
|
+
* claimIncentives Response
|
|
247
|
+
*/
|
|
248
|
+
export type ClaimIncentivesResponse = {
|
|
249
|
+
txHash: string | null;
|
|
250
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ethers
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
2
|
import { DefinitionFlow } from './constants';
|
|
3
|
-
import { type ClusterDefinition } from './types';
|
|
3
|
+
import { type ProviderType, type ClusterDefinition } from './types';
|
|
4
4
|
export declare const hexWithout0x: (hex: string) => string;
|
|
5
5
|
export declare const strToUint8Array: (str: string) => Uint8Array;
|
|
6
6
|
export declare const definitionFlow: (clusterDefinition: ClusterDefinition) => DefinitionFlow | null;
|
|
7
|
-
export declare const findDeployedBytecode: (contractAddress: string, provider:
|
|
8
|
-
export declare const isContractAvailable: (contractAddress: string, provider:
|
|
9
|
-
export declare const getProvider: (chainId: number) => ethers.
|
|
7
|
+
export declare const findDeployedBytecode: (contractAddress: string, provider: ProviderType) => Promise<string>;
|
|
8
|
+
export declare const isContractAvailable: (contractAddress: string, provider: ProviderType, bytecode?: string) => Promise<boolean>;
|
|
9
|
+
export declare const getProvider: (chainId: number, rpcUrl?: string) => ethers.JsonRpcProvider;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { type ClusterDefinition, type ClusterLock, type DepositData, type DistributedValidator } from '../types.js';
|
|
2
|
+
import { type ClusterDefinition, type ClusterLock, type DepositData, type DistributedValidator, type SafeRpcUrl } from '../types.js';
|
|
3
3
|
/**
|
|
4
4
|
* @param cluster The cluster configuration or the cluster definition
|
|
5
5
|
* @param configOnly a boolean to indicate config hash or definition hash
|
|
@@ -29,4 +29,4 @@ export declare const verifyBuilderRegistration: (validator: DistributedValidator
|
|
|
29
29
|
};
|
|
30
30
|
export declare const verifyNodeSignatures: (clusterLock: ClusterLock) => boolean;
|
|
31
31
|
export declare const signingRoot: (domain: Uint8Array, messageBuffer: Buffer) => Uint8Array;
|
|
32
|
-
export declare const isValidClusterLock: (clusterLock: ClusterLock) => Promise<boolean>;
|
|
32
|
+
export declare const isValidClusterLock: (clusterLock: ClusterLock, safeRpcUrl?: SafeRpcUrl) => Promise<boolean>;
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { type TypedMessage } from '@metamask/eth-sig-util';
|
|
2
2
|
import { type EIP712TypedData } from '@safe-global/safe-core-sdk-types';
|
|
3
|
-
|
|
3
|
+
import { type SafeRpcUrl } from '../types';
|
|
4
|
+
export declare const validateAddressSignature: ({ address, token, data, chainId, safeRpcUrl, }: {
|
|
4
5
|
address: string;
|
|
5
6
|
token: string;
|
|
6
7
|
data: TypedMessage<any>;
|
|
7
8
|
chainId: number;
|
|
9
|
+
safeRpcUrl?: string | undefined;
|
|
8
10
|
}) => Promise<boolean>;
|
|
9
11
|
export declare const validateEOASignature: ({ token, data, address, }: {
|
|
10
12
|
token: string;
|
|
11
13
|
data: TypedMessage<any>;
|
|
12
14
|
address: string;
|
|
13
15
|
}) => boolean;
|
|
14
|
-
export declare const validateSmartContractSignature: ({ token, data, address, chainId, }: {
|
|
16
|
+
export declare const validateSmartContractSignature: ({ token, data, address, chainId, safeRpcUrl, }: {
|
|
15
17
|
token: string;
|
|
16
18
|
data: EIP712TypedData;
|
|
17
19
|
address: string;
|
|
18
20
|
chainId: number;
|
|
21
|
+
safeRpcUrl?: string | undefined;
|
|
19
22
|
}) => Promise<boolean>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obolnetwork/obol-sdk",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.6",
|
|
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"
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"lint": "eslint \"{src,test}/**/*.{js,ts}\" --fix",
|
|
24
24
|
"lint-ci": "eslint \"{src,test}/**/*.{js,ts}\"",
|
|
25
25
|
"prettier-ci": "prettier --check \"{src,test}/**/*.{js,ts}\"",
|
|
26
|
-
"prettier": "prettier --write \"{src,test}/**/*.{js,ts}\""
|
|
26
|
+
"prettier": "prettier --write \"{src,test}/**/*.{js,ts}\"",
|
|
27
|
+
"docs": "typedoc"
|
|
27
28
|
},
|
|
28
29
|
"main": "./dist/cjs/src/index.js",
|
|
29
30
|
"module": "./dist/esm/src/index.js",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"eslint-plugin-import": "^2.29.1",
|
|
56
57
|
"eslint-plugin-n": "^16.6.2",
|
|
57
58
|
"eslint-plugin-promise": "^6.1.1",
|
|
58
|
-
"ethers": "6.
|
|
59
|
+
"ethers": "^6.13.5",
|
|
59
60
|
"nock": "^13.5.3",
|
|
60
61
|
"pdf-parse": "^1.1.1",
|
|
61
62
|
"semver": "^7.6.0",
|
|
@@ -79,8 +80,8 @@
|
|
|
79
80
|
"release-it": "^17.2.1",
|
|
80
81
|
"ts-jest": "^28.0.8",
|
|
81
82
|
"tsup": "^6.7.0",
|
|
82
|
-
"typedoc": "^0.
|
|
83
|
-
"typedoc-plugin-markdown": "^4.
|
|
83
|
+
"typedoc": "^0.28.0",
|
|
84
|
+
"typedoc-plugin-markdown": "^4.5.2",
|
|
84
85
|
"typescript": "~5.3.3"
|
|
85
86
|
},
|
|
86
87
|
"engines": {
|
package/src/incentiveHelpers.ts
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import { type ETH_ADDRESS } from './types';
|
|
2
|
-
import {
|
|
3
|
-
Contract,
|
|
4
|
-
type JsonRpcApiProvider,
|
|
5
|
-
type JsonRpcProvider,
|
|
6
|
-
type Provider,
|
|
7
|
-
type Signer,
|
|
8
|
-
} from 'ethers';
|
|
1
|
+
import { type ProviderType, type SignerType, type ETH_ADDRESS } from './types';
|
|
2
|
+
import { Contract } from 'ethers';
|
|
9
3
|
import { MerkleDistributorABI } from './abi/MerkleDistributorWithDeadline';
|
|
10
|
-
import { getProvider } from './utils';
|
|
11
4
|
|
|
12
5
|
export const claimIncentivesFromMerkleDistributor = async (incentivesData: {
|
|
13
|
-
signer:
|
|
6
|
+
signer: SignerType;
|
|
14
7
|
contractAddress: ETH_ADDRESS;
|
|
15
8
|
index: number;
|
|
16
9
|
operatorAddress: ETH_ADDRESS;
|
|
@@ -41,18 +34,15 @@ export const claimIncentivesFromMerkleDistributor = async (incentivesData: {
|
|
|
41
34
|
};
|
|
42
35
|
|
|
43
36
|
export const isClaimedFromMerkleDistributor = async (
|
|
44
|
-
chainId: number,
|
|
45
37
|
contractAddress: ETH_ADDRESS,
|
|
46
38
|
index: number,
|
|
47
|
-
provider:
|
|
39
|
+
provider: ProviderType | undefined | null,
|
|
48
40
|
): Promise<boolean> => {
|
|
49
41
|
try {
|
|
50
|
-
const clientProvider = provider ?? getProvider(chainId);
|
|
51
|
-
|
|
52
42
|
const contract = new Contract(
|
|
53
43
|
contractAddress,
|
|
54
44
|
MerkleDistributorABI.abi,
|
|
55
|
-
|
|
45
|
+
provider,
|
|
56
46
|
);
|
|
57
47
|
|
|
58
48
|
const claimed = await contract.isClaimed(BigInt(index));
|