@obolnetwork/obol-sdk 2.1.1 → 2.2.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 +4 -1
- package/dist/cjs/src/constants.js +9 -1
- package/dist/cjs/src/index.js +2 -0
- package/dist/cjs/src/types.js +18 -1
- package/dist/cjs/src/utils.js +11 -1
- package/dist/cjs/src/verification/common.js +35 -28
- package/dist/cjs/src/verification/signature-validator.js +72 -0
- package/dist/cjs/test/fixtures.js +88 -1
- package/dist/cjs/test/methods.test.js +4 -0
- package/dist/esm/package.json +4 -1
- package/dist/esm/src/constants.js +8 -0
- package/dist/esm/src/index.js +2 -0
- package/dist/esm/src/types.js +17 -0
- package/dist/esm/src/utils.js +10 -1
- package/dist/esm/src/verification/common.js +35 -28
- package/dist/esm/src/verification/signature-validator.js +63 -0
- package/dist/esm/test/fixtures.js +87 -0
- package/dist/esm/test/methods.test.js +5 -1
- package/dist/types/src/constants.d.ts +1 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/types.d.ts +7 -1
- package/dist/types/src/utils.d.ts +2 -1
- package/dist/types/src/verification/signature-validator.d.ts +19 -0
- package/dist/types/test/fixtures.d.ts +51 -0
- package/package.json +4 -1
- package/src/constants.ts +10 -0
- package/src/index.ts +2 -0
- package/src/types.ts +23 -0
- package/src/utils.ts +11 -3
- package/src/verification/common.ts +40 -31
- package/src/verification/signature-validator.ts +96 -0
package/dist/cjs/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obolnetwork/obol-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A package for creating Distributed Validators using the Obol API.",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/obolnetwork/obol-sdk/issues"
|
|
@@ -44,9 +44,12 @@
|
|
|
44
44
|
"@chainsafe/discv5": "^0.5.1",
|
|
45
45
|
"@chainsafe/ssz": "^0.14.0",
|
|
46
46
|
"@metamask/eth-sig-util": "^7.0.1",
|
|
47
|
+
"@safe-global/protocol-kit": "4.1.1",
|
|
48
|
+
"@safe-global/safe-core-sdk-types": "5.1.0",
|
|
47
49
|
"@types/pdf-parse": "^1.1.4",
|
|
48
50
|
"ajv": "^8.12.0",
|
|
49
51
|
"cross-fetch": "^3.1.5",
|
|
52
|
+
"dotenv": "^16.4.7",
|
|
50
53
|
"elliptic": "^6.5.4",
|
|
51
54
|
"eslint-config-standard-with-typescript": "^43.0.1",
|
|
52
55
|
"eslint-plugin-import": "^2.29.1",
|
|
@@ -23,10 +23,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.OBOL_SDK_EMAIL = exports.DEFAULT_RETROACTIVE_FUNDING_TOTAL_SPLIT = exports.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT = exports.CHAIN_CONFIGURATION = exports.AVAILABLE_SPLITTER_CHAINS = exports.TERMS_AND_CONDITIONS_HASH = exports.TERMS_AND_CONDITIONS_URL = exports.TERMS_AND_CONDITIONS_VERSION = exports.ETHER_TO_GWEI = exports.DEFAULT_CHAIN_ID = exports.DEFAULT_BASE_VERSION = exports.DEFAULT_BASE_URL = exports.DefinitionFlow = exports.GENESIS_VALIDATOR_ROOT = exports.DOMAIN_DEPOSIT = exports.DOMAIN_APPLICATION_BUILDER = exports.SDK_VERSION = exports.CONFIG_VERSION = exports.DKG_ALGORITHM = exports.signEnrPayload = exports.signOperatorConfigHashPayload = exports.signCreatorConfigHashPayload = exports.ENRTypedMessage = exports.OperatorTypedMessage = exports.OperatorConfigHashSigningTypes = exports.EnrSigningTypes = exports.CreatorTypedMessage = exports.Domain = exports.TermsAndConditionsSigningTypes = exports.CreatorConfigHashSigningTypes = exports.EIP712_DOMAIN_VERSION = exports.EIP712_DOMAIN_NAME = exports.CONFLICT_ERROR_MSG = void 0;
|
|
26
|
+
exports.PROVIDER_MAP = exports.OBOL_SDK_EMAIL = exports.DEFAULT_RETROACTIVE_FUNDING_TOTAL_SPLIT = exports.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT = exports.CHAIN_CONFIGURATION = exports.AVAILABLE_SPLITTER_CHAINS = exports.TERMS_AND_CONDITIONS_HASH = exports.TERMS_AND_CONDITIONS_URL = exports.TERMS_AND_CONDITIONS_VERSION = exports.ETHER_TO_GWEI = exports.DEFAULT_CHAIN_ID = exports.DEFAULT_BASE_VERSION = exports.DEFAULT_BASE_URL = exports.DefinitionFlow = exports.GENESIS_VALIDATOR_ROOT = exports.DOMAIN_DEPOSIT = exports.DOMAIN_APPLICATION_BUILDER = exports.SDK_VERSION = exports.CONFIG_VERSION = exports.DKG_ALGORITHM = exports.signEnrPayload = exports.signOperatorConfigHashPayload = exports.signCreatorConfigHashPayload = exports.ENRTypedMessage = exports.OperatorTypedMessage = exports.OperatorConfigHashSigningTypes = exports.EnrSigningTypes = exports.CreatorTypedMessage = exports.Domain = exports.TermsAndConditionsSigningTypes = exports.CreatorConfigHashSigningTypes = exports.EIP712_DOMAIN_VERSION = exports.EIP712_DOMAIN_NAME = exports.CONFLICT_ERROR_MSG = void 0;
|
|
27
27
|
const pjson = __importStar(require("../package.json"));
|
|
28
28
|
const types_1 = require("./types");
|
|
29
29
|
const bytecodes_1 = require("./bytecodes");
|
|
30
|
+
const dotenv = __importStar(require("dotenv"));
|
|
31
|
+
dotenv.config();
|
|
30
32
|
exports.CONFLICT_ERROR_MSG = 'Conflict';
|
|
31
33
|
exports.EIP712_DOMAIN_NAME = 'Obol';
|
|
32
34
|
exports.EIP712_DOMAIN_VERSION = '1';
|
|
@@ -171,3 +173,9 @@ exports.CHAIN_CONFIGURATION = {
|
|
|
171
173
|
exports.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT = 1;
|
|
172
174
|
exports.DEFAULT_RETROACTIVE_FUNDING_TOTAL_SPLIT = 0.1;
|
|
173
175
|
exports.OBOL_SDK_EMAIL = 'sdk@dvlabs.tech';
|
|
176
|
+
exports.PROVIDER_MAP = {
|
|
177
|
+
1: `${process.env.RPC_MAINNET}`, // Mainnet
|
|
178
|
+
17000: `${process.env.RPC_HOLESKY}`, // Holesky
|
|
179
|
+
11155111: `${process.env.RPC_SEPOLIA}`, // Sepolia
|
|
180
|
+
100: `${process.env.RPC_GNOSIS}`, // Gnosis
|
|
181
|
+
};
|
package/dist/cjs/src/index.js
CHANGED
|
@@ -36,6 +36,7 @@ const splitHelpers_js_1 = require("./splitHelpers.js");
|
|
|
36
36
|
const utils_js_1 = require("./utils.js");
|
|
37
37
|
__exportStar(require("./types.js"), exports);
|
|
38
38
|
__exportStar(require("./services.js"), exports);
|
|
39
|
+
__exportStar(require("./verification/signature-validator.js"), exports);
|
|
39
40
|
/**
|
|
40
41
|
* Obol sdk Client can be used for creating, managing and activating distributed validators.
|
|
41
42
|
*/
|
|
@@ -74,6 +75,7 @@ class Client extends base_js_1.Base {
|
|
|
74
75
|
address,
|
|
75
76
|
version: constants_js_1.TERMS_AND_CONDITIONS_VERSION,
|
|
76
77
|
terms_and_conditions_hash: termsAndConditionsHash,
|
|
78
|
+
fork_version: this.fork_version,
|
|
77
79
|
};
|
|
78
80
|
const termsAndConditionsSignature = yield this.signer.signTypedData((0, constants_js_1.Domain)(), constants_js_1.TermsAndConditionsSigningTypes, {
|
|
79
81
|
terms_and_conditions_hash: termsAndConditionsHash,
|
package/dist/cjs/src/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FORK_MAPPING = void 0;
|
|
3
|
+
exports.FORK_NAMES = exports.FORK_MAPPING = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Permitted ChainID's
|
|
6
6
|
*/
|
|
@@ -14,4 +14,21 @@ var FORK_MAPPING;
|
|
|
14
14
|
FORK_MAPPING[FORK_MAPPING["0x00000064"] = 100] = "0x00000064";
|
|
15
15
|
/** Holesky. */
|
|
16
16
|
FORK_MAPPING[FORK_MAPPING["0x01017000"] = 17000] = "0x01017000";
|
|
17
|
+
/** Sepolia. */
|
|
18
|
+
FORK_MAPPING[FORK_MAPPING["0x90000069"] = 11155111] = "0x90000069";
|
|
17
19
|
})(FORK_MAPPING || (exports.FORK_MAPPING = FORK_MAPPING = {}));
|
|
20
|
+
/**
|
|
21
|
+
* Permitted Chain Names
|
|
22
|
+
*/
|
|
23
|
+
exports.FORK_NAMES = {
|
|
24
|
+
/** Mainnet. */
|
|
25
|
+
[FORK_MAPPING['0x00000000']]: 'mainnet',
|
|
26
|
+
/** Goerli/Prater. */
|
|
27
|
+
[FORK_MAPPING['0x00001020']]: 'goerli',
|
|
28
|
+
/** Gnosis Chain. */
|
|
29
|
+
[FORK_MAPPING['0x00000064']]: 'gnosis',
|
|
30
|
+
/** Holesky. */
|
|
31
|
+
[FORK_MAPPING['0x01017000']]: 'holesky',
|
|
32
|
+
/** Sepolia. */
|
|
33
|
+
[FORK_MAPPING['0x90000069']]: 'sepolia',
|
|
34
|
+
};
|
package/dist/cjs/src/utils.js
CHANGED
|
@@ -9,8 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.isContractAvailable = exports.findDeployedBytecode = exports.definitionFlow = exports.strToUint8Array = exports.hexWithout0x = void 0;
|
|
12
|
+
exports.getProvider = exports.isContractAvailable = exports.findDeployedBytecode = exports.definitionFlow = exports.strToUint8Array = exports.hexWithout0x = void 0;
|
|
13
|
+
const ethers_1 = require("ethers");
|
|
13
14
|
const constants_1 = require("./constants");
|
|
15
|
+
const types_1 = require("./types");
|
|
14
16
|
const hexWithout0x = (hex) => {
|
|
15
17
|
return hex.slice(2, hex.length);
|
|
16
18
|
};
|
|
@@ -65,3 +67,11 @@ const isContractAvailable = (contractAddress, provider, bytecode) => __awaiter(v
|
|
|
65
67
|
return !!code && code !== '0x' && code !== '0x0';
|
|
66
68
|
});
|
|
67
69
|
exports.isContractAvailable = isContractAvailable;
|
|
70
|
+
const getProvider = (chainId) => {
|
|
71
|
+
const rpcUrl = constants_1.PROVIDER_MAP[chainId];
|
|
72
|
+
if (!rpcUrl) {
|
|
73
|
+
throw new Error(`No provider configured for ${types_1.FORK_NAMES[chainId]}`);
|
|
74
|
+
}
|
|
75
|
+
return new ethers_1.ethers.JsonRpcProvider(rpcUrl);
|
|
76
|
+
};
|
|
77
|
+
exports.getProvider = getProvider;
|
|
@@ -43,13 +43,12 @@ const types_js_1 = require("../types.js");
|
|
|
43
43
|
const semver = __importStar(require("semver"));
|
|
44
44
|
const v1_6_0_js_1 = require("./v1.6.0.js");
|
|
45
45
|
const v1_7_0_js_1 = require("./v1.7.0.js");
|
|
46
|
-
const ethers_1 = require("ethers");
|
|
47
46
|
const constants_js_1 = require("../constants.js");
|
|
48
|
-
const eth_sig_util_1 = require("@metamask/eth-sig-util");
|
|
49
47
|
const sszTypes_js_1 = require("./sszTypes.js");
|
|
50
48
|
const utils_js_1 = require("../utils.js");
|
|
51
49
|
const discv5_1 = require("@chainsafe/discv5");
|
|
52
50
|
const v1_8_0_js_1 = require("./v1.8.0.js");
|
|
51
|
+
const signature_validator_js_1 = require("./signature-validator.js");
|
|
53
52
|
// cluster-definition hash
|
|
54
53
|
/**
|
|
55
54
|
* @param cluster The cluster configuration or the cluster definition
|
|
@@ -109,62 +108,70 @@ const clusterLockHash = (clusterLock) => {
|
|
|
109
108
|
exports.clusterLockHash = clusterLockHash;
|
|
110
109
|
// Lock verification
|
|
111
110
|
// cluster-definition signatures verification
|
|
112
|
-
const
|
|
111
|
+
const validatePOSTConfigHashSigner = (address, signature, configHash, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
113
112
|
try {
|
|
114
|
-
const sig = ethers_1.ethers.Signature.from(signature);
|
|
115
113
|
const data = (0, constants_js_1.signCreatorConfigHashPayload)({ creator_config_hash: configHash }, chainId);
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
return yield (0, signature_validator_js_1.validateAddressSignature)({
|
|
115
|
+
address,
|
|
116
|
+
token: signature,
|
|
117
|
+
data,
|
|
118
|
+
chainId,
|
|
119
|
+
});
|
|
118
120
|
}
|
|
119
121
|
catch (err) {
|
|
120
122
|
throw err;
|
|
121
123
|
}
|
|
122
|
-
};
|
|
123
|
-
const
|
|
124
|
+
});
|
|
125
|
+
const validatePUTConfigHashSigner = (address, signature, configHash, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
124
126
|
try {
|
|
125
|
-
const sig = ethers_1.ethers.Signature.from(signature);
|
|
126
127
|
const data = (0, constants_js_1.signOperatorConfigHashPayload)({ operator_config_hash: configHash }, chainId);
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
return yield (0, signature_validator_js_1.validateAddressSignature)({
|
|
129
|
+
address,
|
|
130
|
+
token: signature,
|
|
131
|
+
data,
|
|
132
|
+
chainId,
|
|
133
|
+
});
|
|
129
134
|
}
|
|
130
135
|
catch (err) {
|
|
131
136
|
throw err;
|
|
132
137
|
}
|
|
133
|
-
};
|
|
134
|
-
const
|
|
138
|
+
});
|
|
139
|
+
const validateEnrSigner = (address, signature, payload, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
135
140
|
try {
|
|
136
|
-
const sig = ethers_1.ethers.Signature.from(signature);
|
|
137
141
|
const data = (0, constants_js_1.signEnrPayload)({ enr: payload }, chainId);
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
return yield (0, signature_validator_js_1.validateAddressSignature)({
|
|
143
|
+
address,
|
|
144
|
+
token: signature,
|
|
145
|
+
data,
|
|
146
|
+
chainId,
|
|
147
|
+
});
|
|
140
148
|
}
|
|
141
149
|
catch (err) {
|
|
142
150
|
throw err;
|
|
143
151
|
}
|
|
144
|
-
};
|
|
145
|
-
const verifyDefinitionSignatures = (clusterDefinition, definitionType) => {
|
|
152
|
+
});
|
|
153
|
+
const verifyDefinitionSignatures = (clusterDefinition, definitionType) => __awaiter(void 0, void 0, void 0, function* () {
|
|
146
154
|
if (definitionType === constants_js_1.DefinitionFlow.Charon) {
|
|
147
155
|
return true;
|
|
148
156
|
}
|
|
149
157
|
else {
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
158
|
+
const isPOSTConfigHashSignerValid = yield validatePOSTConfigHashSigner(clusterDefinition.creator.address, clusterDefinition.creator.config_signature, clusterDefinition.config_hash, types_js_1.FORK_MAPPING[clusterDefinition.fork_version]);
|
|
159
|
+
if (!isPOSTConfigHashSignerValid) {
|
|
152
160
|
return false;
|
|
153
161
|
}
|
|
154
162
|
if (definitionType === constants_js_1.DefinitionFlow.Solo) {
|
|
155
163
|
return true;
|
|
156
164
|
}
|
|
157
|
-
return clusterDefinition.operators.every(operator => {
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
if (
|
|
161
|
-
enrSigner !== operator.address.toLowerCase()) {
|
|
165
|
+
return clusterDefinition.operators.every((operator) => __awaiter(void 0, void 0, void 0, function* () {
|
|
166
|
+
const isPUTConfigHashSignerValid = yield validatePUTConfigHashSigner(operator.address, operator.config_signature, clusterDefinition.config_hash, types_js_1.FORK_MAPPING[clusterDefinition.fork_version]);
|
|
167
|
+
const isENRSignerValid = yield validateEnrSigner(operator.address, operator.enr_signature, operator.enr, types_js_1.FORK_MAPPING[clusterDefinition.fork_version]);
|
|
168
|
+
if (!isPUTConfigHashSignerValid || !isENRSignerValid) {
|
|
162
169
|
return false;
|
|
163
170
|
}
|
|
164
171
|
return true;
|
|
165
|
-
});
|
|
172
|
+
}));
|
|
166
173
|
}
|
|
167
|
-
};
|
|
174
|
+
});
|
|
168
175
|
// cluster-lock data verification
|
|
169
176
|
const computeSigningRoot = (sszObjectRoot, domain) => {
|
|
170
177
|
const signingRootDefaultValue = sszTypes_js_1.signingRootType.defaultValue();
|
|
@@ -295,7 +302,7 @@ const isValidClusterLock = (clusterLock) => __awaiter(void 0, void 0, void 0, fu
|
|
|
295
302
|
if (definitionType == null) {
|
|
296
303
|
return false;
|
|
297
304
|
}
|
|
298
|
-
const isValidDefinitionData = verifyDefinitionSignatures(clusterLock.cluster_definition, definitionType);
|
|
305
|
+
const isValidDefinitionData = yield verifyDefinitionSignatures(clusterLock.cluster_definition, definitionType);
|
|
299
306
|
if (!isValidDefinitionData) {
|
|
300
307
|
return false;
|
|
301
308
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.validateSmartContractSignature = exports.validateEOASignature = exports.validateAddressSignature = void 0;
|
|
16
|
+
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
17
|
+
const ethers_1 = require("ethers");
|
|
18
|
+
const eth_sig_util_1 = require("@metamask/eth-sig-util");
|
|
19
|
+
const protocol_kit_1 = __importDefault(require("@safe-global/protocol-kit"));
|
|
20
|
+
const constants_1 = require("../constants");
|
|
21
|
+
const utils_1 = require("@safe-global/protocol-kit/dist/src/utils");
|
|
22
|
+
const utils_2 = require("../utils");
|
|
23
|
+
const validateAddressSignature = ({ address, token, data, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
try {
|
|
25
|
+
const provider = (0, utils_2.getProvider)(chainId);
|
|
26
|
+
if (provider) {
|
|
27
|
+
const contractAddress = yield (0, utils_2.isContractAvailable)(address, provider);
|
|
28
|
+
if (contractAddress) {
|
|
29
|
+
return yield (0, exports.validateSmartContractSignature)({
|
|
30
|
+
token,
|
|
31
|
+
data: data,
|
|
32
|
+
address,
|
|
33
|
+
chainId,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return (0, exports.validateEOASignature)({ token, data, address });
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return (0, exports.validateEOASignature)({ token, data, address });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
exports.validateAddressSignature = validateAddressSignature;
|
|
44
|
+
const validateEOASignature = ({ token, data, address, }) => {
|
|
45
|
+
try {
|
|
46
|
+
const sig = ethers_1.ethers.Signature.from(token);
|
|
47
|
+
const digest = eth_sig_util_1.TypedDataUtils.eip712Hash(data, eth_sig_util_1.SignTypedDataVersion.V4);
|
|
48
|
+
return (ethers_1.ethers.recoverAddress(digest, sig).toLowerCase() ===
|
|
49
|
+
address.toLocaleLowerCase());
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
console.error(`validate EOA Signature error: ${err}`);
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
exports.validateEOASignature = validateEOASignature;
|
|
57
|
+
const validateSmartContractSignature = ({ token, data, address, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
+
try {
|
|
59
|
+
const provider = constants_1.PROVIDER_MAP[chainId];
|
|
60
|
+
const protocolKit = yield protocol_kit_1.default.init({
|
|
61
|
+
provider,
|
|
62
|
+
safeAddress: address,
|
|
63
|
+
});
|
|
64
|
+
const messageHash = (0, utils_1.hashTypedData)(data);
|
|
65
|
+
const isValidSignature = yield protocolKit.isValidSignature(messageHash, token);
|
|
66
|
+
return isValidSignature;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
throw new Error(`Error validating smart contract signature: ${err.message}`);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
exports.validateSmartContractSignature = validateSmartContractSignature;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.nullDepositAmountsClusterLockV1X8 = exports.clusterLockV1X8 = exports.clusterConfigV1X8 = exports.clusterLockV1X7 = exports.clusterConfigV1X7 = exports.clusterLockV1X6 = exports.enr = void 0;
|
|
3
|
+
exports.clusterLockWithSafe = exports.nullDepositAmountsClusterLockV1X8 = exports.clusterLockV1X8 = exports.clusterConfigV1X8 = exports.clusterLockV1X7 = exports.clusterConfigV1X7 = exports.clusterLockV1X6 = exports.enr = void 0;
|
|
4
4
|
exports.enr = 'enr:-HW4QLlrtMjFLGkFT1bwdGbvZQlH8hLi0M2g44JAxEYP3BZmYpcsy9Q56HPPD87fMucjvLv4-obEFacpsg0ehRilbHeAgmlkgnY0iXNlY3AyNTZrMaEDRaa5o2aSgqyFq_ERZcQTztrOij1mFtXX1bJuVI6ieak';
|
|
5
5
|
// v1.6.0
|
|
6
6
|
exports.clusterLockV1X6 = {
|
|
@@ -423,3 +423,90 @@ exports.nullDepositAmountsClusterLockV1X8 = {
|
|
|
423
423
|
'0xdb6332a4ca9c41592511e7480c835b449fea120430e759735f3c24f1a6d496551a516151d2baae21d0cc9469b28dc1122b672af40ebb0e77045da92e0da6a03500',
|
|
424
424
|
],
|
|
425
425
|
};
|
|
426
|
+
exports.clusterLockWithSafe = {
|
|
427
|
+
cluster_definition: {
|
|
428
|
+
name: 'Rainy cluster',
|
|
429
|
+
creator: {
|
|
430
|
+
address: '0xEF43Ff87070247EC9D28B482D6474318e9DAFc98',
|
|
431
|
+
config_signature: '0x0c4aaafcef722cf770b419d47a21571b3c73275185a1b719e5709168af6327eb2ee392134e660d6e4ea113abd184dd4f2bd8ee09a4ae33f434433f7575873b981c',
|
|
432
|
+
},
|
|
433
|
+
operators: [
|
|
434
|
+
{
|
|
435
|
+
address: '0xe5b709A14859EdF820347D78E587b1634B0ec771',
|
|
436
|
+
enr: 'enr:-HW4QGrhMVQGLtKv_KlubzcVZM9AUsSVgDPtq4k_0q344ZtWJ6tD4riMP5jfWXXdHIklAm_pHdQv0MbTE1DrXmuEM7yAgmlkgnY0iXNlY3AyNTZrMaECa_cfUuFYiuFQp_dUEEicCBdFWNfzm8QhrNhBwey8PBg',
|
|
437
|
+
config_signature: '0xad813cd706d7469b560570ef13b0afdf36d0637e9bc5362ec358c218085d9b231b1377f0078e1ed9c2af99fddb3d7608c03bf8aee6edc931c73d7204a7fdee181b',
|
|
438
|
+
enr_signature: '0x304c022e74c13bfd492219efc52fb133f728afa01fefa9fe1d2540ce7c23ca730dd8248b0ad76630dd120975085d77fba20c050620f1e9583590d003110dbca41c',
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
address: '0x83b7CA5be230A50DEE511657CCFF262ba04D0353',
|
|
442
|
+
enr: 'enr:-HW4QNGbmr_0YhIeTUQfljlDGGCnR8RGhtWr_gjMI8a5BwigGur2qFgGZrqSumAvk4gX9ciP2Tu74uOdOZPw6nvTi7aAgmlkgnY0iXNlY3AyNTZrMaEC0nrshQsWtEOphaLrZVTzPFOz8EAJweGbhXDtSsXPiLY',
|
|
443
|
+
config_signature: '0x41dfb02ff13775d53ad3f739151c44952ff98a3283d124b6f69782e7458150e92771e32f965803391818d23ad95c9c7bcba15e896c3a576d1a700a16d8cb29fe1b',
|
|
444
|
+
enr_signature: '0x388460abfdeded56839e4ae1480ea48a70ac44a89963bda24152e4f879a9d22918c3e77733f2ccaed5c2745f503565d651a357c6a50634a597d61e16c384961e1c',
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
address: '0x123C1cD7AeE10b525D09b848D4A62596958f7D9C',
|
|
448
|
+
enr: 'enr:-HW4QMpDdYHJR3TlnWsnuIKfbmg2aRMMcAFlhTuuZa0Grd3dMFC0AEPHvHM2cKboULC4RUl2Dz7-LpwL2EJRGhJzxcyAgmlkgnY0iXNlY3AyNTZrMaEC73iR5dcgO_bJ8tvsHLrFglwspGFhaAbiBtGAHAJPD9c',
|
|
449
|
+
config_signature: '0x91d23aefc02263fdf0edd0dcfdf26eee01c4d673b97a91a099fc10dfc01f55fa690eccc809658ea2ed17383df355f80a62bd96df15e40a2e2f740189fa6537f61b',
|
|
450
|
+
enr_signature: '0x1035b284df3b1d60434bfe2d139f1472ed29663e2af719779bb5da35537f202032ab0f7cdc540c724c8e80bedfba247809d741260201fbb5bcbfc7f0813334241b',
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
address: '0x169212AE1A834C1E0efd8C827Abdbc2b5557B86C', // safe address
|
|
454
|
+
enr: 'enr:-HW4QPwheIq51G9r9k-6GYrhp9-y-hN2SSowqgQemvPyBu9cOKERqPeqy0JuZ0yKyWiji406eK8fFeHX5fKU-6OI3u6AgmlkgnY0iXNlY3AyNTZrMaECaARWVFt5KNkHPno5YYdFBUrkLU5EmOB3K0Ns9hp-s-s',
|
|
455
|
+
config_signature: '0xf97cc2536afe96e43e07aac140254cea37b0345573b12476f8840e571095d72049aa9e03a099ef2965523f83648c4323cd16ec2ee3f5e6efac177da13bcf6eb21c',
|
|
456
|
+
enr_signature: '0x422f471d54eb19fc52e076bb11fd5c8de895734ed111b66708ef805ae124f87b7519e841e59eccdb75c8328223efd8bb324f3fd7d3048f037419bb83e03caae41b',
|
|
457
|
+
},
|
|
458
|
+
],
|
|
459
|
+
uuid: '3ac43657-b465-49a8-94aa-25b7f7979c2a',
|
|
460
|
+
version: 'v1.8.0',
|
|
461
|
+
timestamp: '2025-01-08T15:18:28.598Z',
|
|
462
|
+
num_validators: 1,
|
|
463
|
+
threshold: 3,
|
|
464
|
+
validators: [
|
|
465
|
+
{
|
|
466
|
+
fee_recipient_address: '0xe5b709A14859EdF820347D78E587b1634B0ec771',
|
|
467
|
+
withdrawal_address: '0xe5b709A14859EdF820347D78E587b1634B0ec771',
|
|
468
|
+
},
|
|
469
|
+
],
|
|
470
|
+
dkg_algorithm: 'default',
|
|
471
|
+
fork_version: '0x01017000',
|
|
472
|
+
deposit_amounts: ['32000000000'],
|
|
473
|
+
config_hash: '0x1849d9434a5ce7a7d15e1e030a48740a307c80424608c6618386d78a2e597fb3',
|
|
474
|
+
definition_hash: '0x85dabfcebf9bf850521cdb65ea6083c462d9ac57eb62d9a9eb47761ec10bc80e',
|
|
475
|
+
},
|
|
476
|
+
distributed_validators: [
|
|
477
|
+
{
|
|
478
|
+
distributed_public_key: '0xb0427b57f3f31da882a1ca5d9980e6164ba4c4d3e2c35fb6699f4e76d88e1aede881e0bdb87c48ac707da282f0c92e92',
|
|
479
|
+
public_shares: [
|
|
480
|
+
'0x8d150f921a54fe258bb57f568288de87e392946124df65861afbe52d2a3be6a1fa09d19beb62f879b0f18b2e3b26f69f',
|
|
481
|
+
'0x8fa69ec7c31eeda66007bc3d49a3d5654dbe6a3c0890898ea5913ed263a0efc3f6744064dbde3ee0cc1d2f08db33b4d7',
|
|
482
|
+
'0xb862933b7b7adb33cfb3de1052f7dd9e45dfa30accda01dfc4d3c38716747504aade8f832fa5a256dcaf13f80dbbb38f',
|
|
483
|
+
'0xb5a15d86945c7ff38e0b09158a3264033e6dbaebf2ec9f3426988e6d24e38b3dbd6fe413d3253b308404bb691757fb2e',
|
|
484
|
+
],
|
|
485
|
+
builder_registration: {
|
|
486
|
+
message: {
|
|
487
|
+
fee_recipient: '0xe5b709a14859edf820347d78e587b1634b0ec771',
|
|
488
|
+
gas_limit: 30000000,
|
|
489
|
+
timestamp: 1696000704,
|
|
490
|
+
pubkey: '0xb0427b57f3f31da882a1ca5d9980e6164ba4c4d3e2c35fb6699f4e76d88e1aede881e0bdb87c48ac707da282f0c92e92',
|
|
491
|
+
},
|
|
492
|
+
signature: '0xa5e4220e7d8e7fd4430590c70a27104473b15c8ea03b2d1571bc86bbbcb443e2b7467f75a7e77b5d9b1a10d5fbc335cf0d59c3b3bc1b6d036b2e22511abcf41373567a15185f011ce0129741f0ae0e9e49759f9c5c0ce62f2a99f30e8c7df996',
|
|
493
|
+
},
|
|
494
|
+
partial_deposit_data: [
|
|
495
|
+
{
|
|
496
|
+
pubkey: '0xb0427b57f3f31da882a1ca5d9980e6164ba4c4d3e2c35fb6699f4e76d88e1aede881e0bdb87c48ac707da282f0c92e92',
|
|
497
|
+
withdrawal_credentials: '0x010000000000000000000000e5b709a14859edf820347d78e587b1634b0ec771',
|
|
498
|
+
amount: '32000000000',
|
|
499
|
+
signature: '0x90aff3cb35c577644cb5fe3036ae8aeb5ac6cc2ce2a33a4332e2e883dc48f8fb71165531862d3035a4b6e3a60215d661021672a59f9406e3bd04b5f88f4f77c5f54a9ff37167807010123cdcc230040e5a485b5eb36704fd276dbf541f7151a8',
|
|
500
|
+
},
|
|
501
|
+
],
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
signature_aggregate: '0x86fdeae3db45215d5f24fc19645f8f95e91fffd1a1d0a87668d3f27724fa735b85fb15de120106b8463ff1d32823813e0f139ee7cb6d3b026c6b81cc96566819817742a13e24ac44fc6571385d5b0fdbaace7e50e2cfbcd692e36b1ca25436e4',
|
|
505
|
+
lock_hash: '0xe03b0fdf6d6a7d38360b0ceac1f0380b051f710e80d0e166b855ef3148d46733',
|
|
506
|
+
node_signatures: [
|
|
507
|
+
'0x564328bcad4cac498aa51b7e7e041cf264e9c65c95138df1fc00d4bf714bc38419c43b5a32662d5c8b747d646d6e77830b2bfd62fa8402e136147c244acdce0300',
|
|
508
|
+
'0xb0e984efd2874fc4bc97bb9c42dccbc723080cf29a20a3cf0b05867ebe87bc430c29a560936000439fcde610ce91452ced763586d3bcca24fbe4fe83bb39202601',
|
|
509
|
+
'0xf3633a8e59db2e8d253ffe1b284f9edab1c1c1aca6288c3a3b2e9cb4eb7e789e23366fc325274f13b7311b9faf53665c80b5cb1f93810713f7b094cd2bec1d9900',
|
|
510
|
+
'0x4067921a5257efe4ceb103f2129faaa7a502781157b3b54e5efca559c558c2b43b89f30962e87df88fbf62250049a31888fcd62735d54b7553e5dc75c3b6ae0901',
|
|
511
|
+
],
|
|
512
|
+
};
|
|
@@ -202,6 +202,10 @@ describe('Cluster Client without a signer', () => {
|
|
|
202
202
|
version: 'null deposit_amounts v1.8.0',
|
|
203
203
|
clusterLock: fixtures_js_1.nullDepositAmountsClusterLockV1X8,
|
|
204
204
|
},
|
|
205
|
+
{
|
|
206
|
+
version: 'Cluster with safe address v1.8.0',
|
|
207
|
+
clusterLock: fixtures_js_1.clusterLockWithSafe,
|
|
208
|
+
},
|
|
205
209
|
])("$version: 'should return true on verified cluster lock'", ({ clusterLock }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
206
210
|
const isValidLock = yield (0, index_1.validateClusterLock)(clusterLock);
|
|
207
211
|
expect(isValidLock).toEqual(true);
|
package/dist/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obolnetwork/obol-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A package for creating Distributed Validators using the Obol API.",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/obolnetwork/obol-sdk/issues"
|
|
@@ -44,9 +44,12 @@
|
|
|
44
44
|
"@chainsafe/discv5": "^0.5.1",
|
|
45
45
|
"@chainsafe/ssz": "^0.14.0",
|
|
46
46
|
"@metamask/eth-sig-util": "^7.0.1",
|
|
47
|
+
"@safe-global/protocol-kit": "4.1.1",
|
|
48
|
+
"@safe-global/safe-core-sdk-types": "5.1.0",
|
|
47
49
|
"@types/pdf-parse": "^1.1.4",
|
|
48
50
|
"ajv": "^8.12.0",
|
|
49
51
|
"cross-fetch": "^3.1.5",
|
|
52
|
+
"dotenv": "^16.4.7",
|
|
50
53
|
"elliptic": "^6.5.4",
|
|
51
54
|
"eslint-config-standard-with-typescript": "^43.0.1",
|
|
52
55
|
"eslint-plugin-import": "^2.29.1",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as pjson from '../package.json';
|
|
2
2
|
import { FORK_MAPPING } from './types';
|
|
3
3
|
import { HOLESKY_MULTICALL_BYTECODE, HOLESKY_OWR_FACTORY_BYTECODE, HOLESKY_SPLITMAIN_BYTECODE, MAINNET_MULTICALL_BYTECODE, MAINNET_OWR_FACTORY_BYTECODE, MAINNET_SPLITMAIN_BYTECODE, } from './bytecodes';
|
|
4
|
+
import * as dotenv from 'dotenv';
|
|
5
|
+
dotenv.config();
|
|
4
6
|
export const CONFLICT_ERROR_MSG = 'Conflict';
|
|
5
7
|
export const EIP712_DOMAIN_NAME = 'Obol';
|
|
6
8
|
export const EIP712_DOMAIN_VERSION = '1';
|
|
@@ -141,3 +143,9 @@ export const CHAIN_CONFIGURATION = {
|
|
|
141
143
|
export const DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT = 1;
|
|
142
144
|
export const DEFAULT_RETROACTIVE_FUNDING_TOTAL_SPLIT = 0.1;
|
|
143
145
|
export const OBOL_SDK_EMAIL = 'sdk@dvlabs.tech';
|
|
146
|
+
export const PROVIDER_MAP = {
|
|
147
|
+
1: `${process.env.RPC_MAINNET}`, // Mainnet
|
|
148
|
+
17000: `${process.env.RPC_HOLESKY}`, // Holesky
|
|
149
|
+
11155111: `${process.env.RPC_SEPOLIA}`, // Sepolia
|
|
150
|
+
100: `${process.env.RPC_GNOSIS}`, // Gnosis
|
|
151
|
+
};
|
package/dist/esm/src/index.js
CHANGED
|
@@ -19,6 +19,7 @@ import { deploySplitterContract, formatSplitRecipients, handleDeployOWRAndSplitt
|
|
|
19
19
|
import { isContractAvailable } from './utils.js';
|
|
20
20
|
export * from './types.js';
|
|
21
21
|
export * from './services.js';
|
|
22
|
+
export * from './verification/signature-validator.js';
|
|
22
23
|
/**
|
|
23
24
|
* Obol sdk Client can be used for creating, managing and activating distributed validators.
|
|
24
25
|
*/
|
|
@@ -57,6 +58,7 @@ export class Client extends Base {
|
|
|
57
58
|
address,
|
|
58
59
|
version: TERMS_AND_CONDITIONS_VERSION,
|
|
59
60
|
terms_and_conditions_hash: termsAndConditionsHash,
|
|
61
|
+
fork_version: this.fork_version,
|
|
60
62
|
};
|
|
61
63
|
const termsAndConditionsSignature = yield this.signer.signTypedData(Domain(), TermsAndConditionsSigningTypes, {
|
|
62
64
|
terms_and_conditions_hash: termsAndConditionsHash,
|
package/dist/esm/src/types.js
CHANGED
|
@@ -11,4 +11,21 @@ export var FORK_MAPPING;
|
|
|
11
11
|
FORK_MAPPING[FORK_MAPPING["0x00000064"] = 100] = "0x00000064";
|
|
12
12
|
/** Holesky. */
|
|
13
13
|
FORK_MAPPING[FORK_MAPPING["0x01017000"] = 17000] = "0x01017000";
|
|
14
|
+
/** Sepolia. */
|
|
15
|
+
FORK_MAPPING[FORK_MAPPING["0x90000069"] = 11155111] = "0x90000069";
|
|
14
16
|
})(FORK_MAPPING || (FORK_MAPPING = {}));
|
|
17
|
+
/**
|
|
18
|
+
* Permitted Chain Names
|
|
19
|
+
*/
|
|
20
|
+
export const FORK_NAMES = {
|
|
21
|
+
/** Mainnet. */
|
|
22
|
+
[FORK_MAPPING['0x00000000']]: 'mainnet',
|
|
23
|
+
/** Goerli/Prater. */
|
|
24
|
+
[FORK_MAPPING['0x00001020']]: 'goerli',
|
|
25
|
+
/** Gnosis Chain. */
|
|
26
|
+
[FORK_MAPPING['0x00000064']]: 'gnosis',
|
|
27
|
+
/** Holesky. */
|
|
28
|
+
[FORK_MAPPING['0x01017000']]: 'holesky',
|
|
29
|
+
/** Sepolia. */
|
|
30
|
+
[FORK_MAPPING['0x90000069']]: 'sepolia',
|
|
31
|
+
};
|
package/dist/esm/src/utils.js
CHANGED
|
@@ -7,7 +7,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
10
|
+
import { ethers } from 'ethers';
|
|
11
|
+
import { DefinitionFlow, PROVIDER_MAP } from './constants';
|
|
12
|
+
import { FORK_NAMES } from './types';
|
|
11
13
|
export const hexWithout0x = (hex) => {
|
|
12
14
|
return hex.slice(2, hex.length);
|
|
13
15
|
};
|
|
@@ -57,3 +59,10 @@ export const isContractAvailable = (contractAddress, provider, bytecode) => __aw
|
|
|
57
59
|
}
|
|
58
60
|
return !!code && code !== '0x' && code !== '0x0';
|
|
59
61
|
});
|
|
62
|
+
export const getProvider = (chainId) => {
|
|
63
|
+
const rpcUrl = PROVIDER_MAP[chainId];
|
|
64
|
+
if (!rpcUrl) {
|
|
65
|
+
throw new Error(`No provider configured for ${FORK_NAMES[chainId]}`);
|
|
66
|
+
}
|
|
67
|
+
return new ethers.JsonRpcProvider(rpcUrl);
|
|
68
|
+
};
|