@obolnetwork/obol-sdk 2.4.5 → 2.5.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/README.md +1 -1
- package/dist/cjs/package.json +4 -2
- package/dist/cjs/src/ajv.js +67 -41
- package/dist/cjs/src/constants.js +1 -1
- package/dist/cjs/src/incentiveHelpers.js +2 -4
- package/dist/cjs/src/incentives.js +1 -1
- package/dist/cjs/src/index.js +25 -27
- package/dist/cjs/src/schema.js +50 -23
- package/dist/cjs/src/services.js +3 -2
- 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/src/verification/v1.8.0.js +18 -0
- package/dist/cjs/test/fixtures.js +125 -17
- package/dist/cjs/test/incentives.test.js +2 -2
- package/dist/cjs/test/methods.test.js +47 -42
- package/dist/esm/package.json +4 -2
- package/dist/esm/src/ajv.js +66 -40
- package/dist/esm/src/constants.js +1 -1
- package/dist/esm/src/incentiveHelpers.js +2 -4
- package/dist/esm/src/incentives.js +1 -1
- package/dist/esm/src/index.js +26 -28
- package/dist/esm/src/schema.js +50 -23
- package/dist/esm/src/services.js +3 -2
- 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/src/verification/v1.8.0.js +18 -0
- package/dist/esm/test/fixtures.js +124 -16
- package/dist/esm/test/incentives.test.js +2 -2
- package/dist/esm/test/methods.test.js +48 -43
- package/dist/types/src/ajv.d.ts +3 -2
- package/dist/types/src/constants.d.ts +1 -1
- package/dist/types/src/incentiveHelpers.d.ts +1 -1
- package/dist/types/src/incentives.d.ts +2 -2
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/schema.d.ts +40 -8
- package/dist/types/src/services.d.ts +3 -2
- package/dist/types/src/types.d.ts +16 -6
- package/dist/types/src/utils.d.ts +1 -1
- package/dist/types/src/verification/common.d.ts +2 -2
- package/dist/types/src/verification/signature-validator.d.ts +5 -2
- package/dist/types/test/fixtures.d.ts +78 -11
- package/package.json +4 -2
- package/src/ajv.ts +91 -52
- package/src/constants.ts +1 -1
- package/src/incentiveHelpers.ts +1 -5
- package/src/incentives.ts +3 -4
- package/src/index.ts +37 -35
- package/src/schema.ts +45 -22
- package/src/services.ts +4 -2
- package/src/types.ts +20 -5
- package/src/utils.ts +7 -4
- package/src/verification/common.ts +13 -1
- package/src/verification/signature-validator.ts +10 -3
- package/src/verification/v1.8.0.ts +24 -0
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ If you're integrating this SDK with a **backend** (e.g., in Node.js), and you st
|
|
|
19
19
|
|
|
20
20
|
## ⚡️ Integration with Safe Wallet
|
|
21
21
|
|
|
22
|
-
When integrating the Obol SDK with a **Safe Wallet**, you
|
|
22
|
+
When integrating the Obol SDK with a **Safe Wallet**, you can either pass an RPC URL OR provide the `RPC_MAINNET` or `RPC_HOLESKY` or `RPC_GNOSIS` or `RPC_SEPOLIA` environment variable, pointing to the correct network's RPC URL. This is required to interact with Safe kit.
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
## Contributing
|
package/dist/cjs/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obolnetwork/obol-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.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"
|
|
@@ -49,6 +49,8 @@
|
|
|
49
49
|
"@safe-global/safe-core-sdk-types": "5.1.0",
|
|
50
50
|
"@types/pdf-parse": "^1.1.4",
|
|
51
51
|
"ajv": "^8.12.0",
|
|
52
|
+
"ajv-formats": "^3.0.1",
|
|
53
|
+
"ajv-keywords": "^5.1.0",
|
|
52
54
|
"cross-fetch": "^3.1.5",
|
|
53
55
|
"dotenv": "^16.4.7",
|
|
54
56
|
"elliptic": "^6.5.4",
|
|
@@ -56,7 +58,7 @@
|
|
|
56
58
|
"eslint-plugin-import": "^2.29.1",
|
|
57
59
|
"eslint-plugin-n": "^16.6.2",
|
|
58
60
|
"eslint-plugin-promise": "^6.1.1",
|
|
59
|
-
"ethers": "6.
|
|
61
|
+
"ethers": "^6.13.5",
|
|
60
62
|
"nock": "^13.5.3",
|
|
61
63
|
"pdf-parse": "^1.1.1",
|
|
62
64
|
"semver": "^7.6.0",
|
package/dist/cjs/src/ajv.js
CHANGED
|
@@ -3,58 +3,84 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.validatePayload = void 0;
|
|
7
|
-
const
|
|
6
|
+
exports.validatePayload = exports.VALID_NON_COMPOUNDING_AMOUNTS = exports.VALID_DEPOSIT_AMOUNTS = void 0;
|
|
7
|
+
const ajv_formats_1 = __importDefault(require("ajv-formats"));
|
|
8
|
+
const ajv_keywords_1 = __importDefault(require("ajv-keywords"));
|
|
8
9
|
const ethers_1 = require("ethers");
|
|
10
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
9
11
|
const constants_1 = require("./constants");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
exports.VALID_DEPOSIT_AMOUNTS = [
|
|
13
|
+
(0, ethers_1.parseUnits)('1', 'gwei').toString(),
|
|
14
|
+
(0, ethers_1.parseUnits)('32', 'gwei').toString(),
|
|
15
|
+
(0, ethers_1.parseUnits)('8', 'gwei').toString(),
|
|
16
|
+
(0, ethers_1.parseUnits)('256', 'gwei').toString(),
|
|
17
|
+
];
|
|
18
|
+
exports.VALID_NON_COMPOUNDING_AMOUNTS = [
|
|
19
|
+
(0, ethers_1.parseUnits)('1', 'gwei').toString(),
|
|
20
|
+
(0, ethers_1.parseUnits)('32', 'gwei').toString(),
|
|
21
|
+
];
|
|
22
|
+
// They dont see defaults set in schema
|
|
23
|
+
const validateRewardsSplitRecipients = (_, data) => {
|
|
24
|
+
var _a;
|
|
25
|
+
const obolRAFSplit = (_a = data.ObolRAFSplit) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT;
|
|
26
|
+
const splitPercentage = data.splitRecipients.reduce((acc, curr) => acc + curr.percentAllocation, 0);
|
|
27
|
+
return splitPercentage + obolRAFSplit === 100;
|
|
28
|
+
};
|
|
29
|
+
const validateTotalSplitRecipients = (_, data) => {
|
|
30
|
+
var _a;
|
|
31
|
+
const obolRAFSplit = (_a = data.ObolRAFSplit) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_RETROACTIVE_FUNDING_TOTAL_SPLIT;
|
|
32
|
+
const splitPercentage = data.splitRecipients.reduce((acc, curr) => acc + curr.percentAllocation, 0);
|
|
33
|
+
return splitPercentage + obolRAFSplit === 100;
|
|
34
|
+
};
|
|
35
|
+
const validateUniqueAddresses = (_, operators) => {
|
|
36
|
+
if (!operators) {
|
|
37
|
+
return false;
|
|
23
38
|
}
|
|
24
|
-
if (
|
|
39
|
+
if (operators.length < 4) {
|
|
25
40
|
return false;
|
|
26
41
|
}
|
|
27
|
-
|
|
42
|
+
if (operators.every(op => op.address === '')) {
|
|
28
43
|
return true;
|
|
29
44
|
}
|
|
45
|
+
if (operators.some(op => op.address.length !== 42)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const addresses = operators.map(op => op.address);
|
|
49
|
+
const uniqueAddresses = new Set(addresses);
|
|
50
|
+
const isUnique = uniqueAddresses.size === addresses.length;
|
|
51
|
+
return isUnique;
|
|
30
52
|
};
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
const ajv = new ajv_1.default({
|
|
54
|
+
allErrors: true,
|
|
55
|
+
useDefaults: true,
|
|
56
|
+
strict: false,
|
|
57
|
+
$data: true,
|
|
58
|
+
});
|
|
59
|
+
(0, ajv_formats_1.default)(ajv);
|
|
60
|
+
(0, ajv_keywords_1.default)(ajv, ['patternRequired']);
|
|
61
|
+
ajv.addKeyword({
|
|
62
|
+
keyword: 'validateRewardsSplitRecipients',
|
|
63
|
+
validate: validateRewardsSplitRecipients,
|
|
64
|
+
schemaType: 'boolean',
|
|
65
|
+
});
|
|
66
|
+
ajv.addKeyword({
|
|
67
|
+
keyword: 'validateTotalSplitRecipients',
|
|
68
|
+
validate: validateTotalSplitRecipients,
|
|
69
|
+
schemaType: 'boolean',
|
|
70
|
+
});
|
|
71
|
+
ajv.addKeyword({
|
|
72
|
+
keyword: 'validateUniqueAddresses',
|
|
73
|
+
validate: validateUniqueAddresses,
|
|
74
|
+
schemaType: 'boolean',
|
|
75
|
+
});
|
|
40
76
|
function validatePayload(data, schema) {
|
|
41
77
|
var _a;
|
|
42
|
-
const ajv = new ajv_1.default();
|
|
43
|
-
ajv.addKeyword({
|
|
44
|
-
keyword: 'validDepositAmounts',
|
|
45
|
-
validate: validDepositAmounts,
|
|
46
|
-
errors: true,
|
|
47
|
-
});
|
|
48
|
-
ajv.addKeyword({
|
|
49
|
-
keyword: 'validateSplitRecipients',
|
|
50
|
-
validate: validateSplitRecipients,
|
|
51
|
-
errors: true,
|
|
52
|
-
});
|
|
53
78
|
const validate = ajv.compile(schema);
|
|
54
|
-
const
|
|
55
|
-
if (!
|
|
56
|
-
|
|
79
|
+
const valid = validate(data);
|
|
80
|
+
if (!valid) {
|
|
81
|
+
const errors = (_a = validate.errors) === null || _a === void 0 ? void 0 : _a.map(e => `${e.instancePath} ${e.message}`).join(', ');
|
|
82
|
+
throw new Error(`Validation failed: ${errors}`);
|
|
57
83
|
}
|
|
58
|
-
return
|
|
84
|
+
return data;
|
|
59
85
|
}
|
|
60
86
|
exports.validatePayload = validatePayload;
|
|
@@ -110,7 +110,7 @@ const signEnrPayload = (payload, chainId) => {
|
|
|
110
110
|
};
|
|
111
111
|
exports.signEnrPayload = signEnrPayload;
|
|
112
112
|
exports.DKG_ALGORITHM = 'default';
|
|
113
|
-
exports.CONFIG_VERSION = 'v1.
|
|
113
|
+
exports.CONFIG_VERSION = 'v1.10.0';
|
|
114
114
|
exports.SDK_VERSION = package_json_1.default.version;
|
|
115
115
|
exports.DOMAIN_APPLICATION_BUILDER = '00000001';
|
|
116
116
|
exports.DOMAIN_DEPOSIT = '03000000';
|
|
@@ -12,7 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.isClaimedFromMerkleDistributor = exports.claimIncentivesFromMerkleDistributor = void 0;
|
|
13
13
|
const ethers_1 = require("ethers");
|
|
14
14
|
const MerkleDistributorWithDeadline_1 = require("./abi/MerkleDistributorWithDeadline");
|
|
15
|
-
const utils_1 = require("./utils");
|
|
16
15
|
const claimIncentivesFromMerkleDistributor = (incentivesData) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
16
|
try {
|
|
18
17
|
const contract = new ethers_1.Contract(incentivesData.contractAddress, MerkleDistributorWithDeadline_1.MerkleDistributorABI.abi, incentivesData.signer);
|
|
@@ -26,10 +25,9 @@ const claimIncentivesFromMerkleDistributor = (incentivesData) => __awaiter(void
|
|
|
26
25
|
}
|
|
27
26
|
});
|
|
28
27
|
exports.claimIncentivesFromMerkleDistributor = claimIncentivesFromMerkleDistributor;
|
|
29
|
-
const isClaimedFromMerkleDistributor = (
|
|
28
|
+
const isClaimedFromMerkleDistributor = (contractAddress, index, provider) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
29
|
try {
|
|
31
|
-
const
|
|
32
|
-
const contract = new ethers_1.Contract(contractAddress, MerkleDistributorWithDeadline_1.MerkleDistributorABI.abi, clientProvider);
|
|
30
|
+
const contract = new ethers_1.Contract(contractAddress, MerkleDistributorWithDeadline_1.MerkleDistributorABI.abi, provider);
|
|
33
31
|
const claimed = yield contract.isClaimed(BigInt(index));
|
|
34
32
|
return claimed;
|
|
35
33
|
}
|
|
@@ -95,7 +95,7 @@ class Incentives {
|
|
|
95
95
|
*/
|
|
96
96
|
isClaimed(contractAddress, index) {
|
|
97
97
|
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
-
return yield (0, incentiveHelpers_1.isClaimedFromMerkleDistributor)(
|
|
98
|
+
return yield (0, incentiveHelpers_1.isClaimedFromMerkleDistributor)(contractAddress, index, this.provider);
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
/**
|
package/dist/cjs/src/index.js
CHANGED
|
@@ -24,7 +24,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.Client = exports.Incentives = void 0;
|
|
27
|
-
const ethers_1 = require("ethers");
|
|
28
27
|
const uuid_1 = require("uuid");
|
|
29
28
|
const base_js_1 = require("./base.js");
|
|
30
29
|
const constants_js_1 = require("./constants.js");
|
|
@@ -39,6 +38,7 @@ __exportStar(require("./types.js"), exports);
|
|
|
39
38
|
__exportStar(require("./services.js"), exports);
|
|
40
39
|
__exportStar(require("./verification/signature-validator.js"), exports);
|
|
41
40
|
__exportStar(require("./verification/common.js"), exports);
|
|
41
|
+
__exportStar(require("./constants.js"), exports);
|
|
42
42
|
var incentives_js_2 = require("./incentives.js");
|
|
43
43
|
Object.defineProperty(exports, "Incentives", { enumerable: true, get: function () { return incentives_js_2.Incentives; } });
|
|
44
44
|
/**
|
|
@@ -120,13 +120,13 @@ class Client extends base_js_1.Base {
|
|
|
120
120
|
* [createObolRewardsSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L141)
|
|
121
121
|
*/
|
|
122
122
|
// add the example reference
|
|
123
|
-
createObolRewardsSplit({ splitRecipients, principalRecipient, etherAmount, ObolRAFSplit = constants_js_1.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT, distributorFee
|
|
123
|
+
createObolRewardsSplit({ splitRecipients, principalRecipient, etherAmount, ObolRAFSplit = constants_js_1.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT, distributorFee, controllerAddress, recoveryAddress, }) {
|
|
124
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
125
125
|
// This method doesnt require T&C signature
|
|
126
126
|
if (!this.signer) {
|
|
127
127
|
throw new Error('Signer is required in createObolRewardsSplit');
|
|
128
128
|
}
|
|
129
|
-
(0, ajv_js_1.validatePayload)({
|
|
129
|
+
const validatedPayload = (0, ajv_js_1.validatePayload)({
|
|
130
130
|
splitRecipients,
|
|
131
131
|
principalRecipient,
|
|
132
132
|
etherAmount,
|
|
@@ -149,9 +149,9 @@ class Client extends base_js_1.Base {
|
|
|
149
149
|
}
|
|
150
150
|
const retroActiveFundingRecipient = {
|
|
151
151
|
account: constants_js_1.CHAIN_CONFIGURATION[this.chainId].RETROACTIVE_FUNDING_ADDRESS.address,
|
|
152
|
-
percentAllocation: ObolRAFSplit,
|
|
152
|
+
percentAllocation: validatedPayload.ObolRAFSplit,
|
|
153
153
|
};
|
|
154
|
-
const copiedSplitRecipients = [...splitRecipients];
|
|
154
|
+
const copiedSplitRecipients = [...validatedPayload.splitRecipients];
|
|
155
155
|
copiedSplitRecipients.push(retroActiveFundingRecipient);
|
|
156
156
|
const { accounts, percentAllocations } = (0, splitHelpers_js_1.formatSplitRecipients)(copiedSplitRecipients);
|
|
157
157
|
const predictedSplitterAddress = yield (0, splitHelpers_js_1.predictSplitterAddress)({
|
|
@@ -159,8 +159,8 @@ class Client extends base_js_1.Base {
|
|
|
159
159
|
accounts,
|
|
160
160
|
percentAllocations,
|
|
161
161
|
chainId: this.chainId,
|
|
162
|
-
distributorFee,
|
|
163
|
-
controllerAddress,
|
|
162
|
+
distributorFee: validatedPayload.distributorFee,
|
|
163
|
+
controllerAddress: validatedPayload.controllerAddress,
|
|
164
164
|
});
|
|
165
165
|
const isSplitterDeployed = yield (0, utils_js_1.isContractAvailable)(predictedSplitterAddress, this.signer.provider);
|
|
166
166
|
const { withdrawal_address, fee_recipient_address } = yield (0, splitHelpers_js_1.handleDeployOWRAndSplitter)({
|
|
@@ -169,12 +169,12 @@ class Client extends base_js_1.Base {
|
|
|
169
169
|
predictedSplitterAddress,
|
|
170
170
|
accounts,
|
|
171
171
|
percentAllocations,
|
|
172
|
-
principalRecipient,
|
|
173
|
-
etherAmount,
|
|
172
|
+
principalRecipient: validatedPayload.principalRecipient,
|
|
173
|
+
etherAmount: validatedPayload.etherAmount,
|
|
174
174
|
chainId: this.chainId,
|
|
175
|
-
distributorFee,
|
|
176
|
-
controllerAddress,
|
|
177
|
-
recoveryAddress,
|
|
175
|
+
distributorFee: validatedPayload.distributorFee,
|
|
176
|
+
controllerAddress: validatedPayload.controllerAddress,
|
|
177
|
+
recoveryAddress: validatedPayload.recoveryAddress,
|
|
178
178
|
});
|
|
179
179
|
return { withdrawal_address, fee_recipient_address };
|
|
180
180
|
});
|
|
@@ -193,13 +193,13 @@ class Client extends base_js_1.Base {
|
|
|
193
193
|
* [createObolTotalSplit](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L168)
|
|
194
194
|
*/
|
|
195
195
|
// add the example reference
|
|
196
|
-
createObolTotalSplit({ splitRecipients, ObolRAFSplit
|
|
196
|
+
createObolTotalSplit({ splitRecipients, ObolRAFSplit, distributorFee, controllerAddress, }) {
|
|
197
197
|
return __awaiter(this, void 0, void 0, function* () {
|
|
198
198
|
// This method doesnt require T&C signature
|
|
199
199
|
if (!this.signer) {
|
|
200
200
|
throw new Error('Signer is required in createObolTotalSplit');
|
|
201
201
|
}
|
|
202
|
-
(0, ajv_js_1.validatePayload)({
|
|
202
|
+
const validatedPayload = (0, ajv_js_1.validatePayload)({
|
|
203
203
|
splitRecipients,
|
|
204
204
|
ObolRAFSplit,
|
|
205
205
|
distributorFee,
|
|
@@ -215,9 +215,9 @@ class Client extends base_js_1.Base {
|
|
|
215
215
|
}
|
|
216
216
|
const retroActiveFundingRecipient = {
|
|
217
217
|
account: constants_js_1.CHAIN_CONFIGURATION[this.chainId].RETROACTIVE_FUNDING_ADDRESS.address,
|
|
218
|
-
percentAllocation: ObolRAFSplit,
|
|
218
|
+
percentAllocation: validatedPayload.ObolRAFSplit,
|
|
219
219
|
};
|
|
220
|
-
const copiedSplitRecipients = [...splitRecipients];
|
|
220
|
+
const copiedSplitRecipients = [...validatedPayload.splitRecipients];
|
|
221
221
|
copiedSplitRecipients.push(retroActiveFundingRecipient);
|
|
222
222
|
const { accounts, percentAllocations } = (0, splitHelpers_js_1.formatSplitRecipients)(copiedSplitRecipients);
|
|
223
223
|
const predictedSplitterAddress = yield (0, splitHelpers_js_1.predictSplitterAddress)({
|
|
@@ -225,8 +225,8 @@ class Client extends base_js_1.Base {
|
|
|
225
225
|
accounts,
|
|
226
226
|
percentAllocations,
|
|
227
227
|
chainId: this.chainId,
|
|
228
|
-
distributorFee,
|
|
229
|
-
controllerAddress,
|
|
228
|
+
distributorFee: validatedPayload.distributorFee,
|
|
229
|
+
controllerAddress: validatedPayload.controllerAddress,
|
|
230
230
|
});
|
|
231
231
|
const isSplitterDeployed = yield (0, utils_js_1.isContractAvailable)(predictedSplitterAddress, this.signer.provider);
|
|
232
232
|
if (!isSplitterDeployed) {
|
|
@@ -235,8 +235,8 @@ class Client extends base_js_1.Base {
|
|
|
235
235
|
accounts,
|
|
236
236
|
percentAllocations,
|
|
237
237
|
chainId: this.chainId,
|
|
238
|
-
distributorFee,
|
|
239
|
-
controllerAddress,
|
|
238
|
+
distributorFee: validatedPayload.distributorFee,
|
|
239
|
+
controllerAddress: validatedPayload.controllerAddress,
|
|
240
240
|
});
|
|
241
241
|
return {
|
|
242
242
|
withdrawal_address: splitterAddress,
|
|
@@ -283,10 +283,8 @@ class Client extends base_js_1.Base {
|
|
|
283
283
|
if (!this.signer) {
|
|
284
284
|
throw new Error('Signer is required in createClusterDefinition');
|
|
285
285
|
}
|
|
286
|
-
(0, ajv_js_1.validatePayload)(newCluster, schema_js_1.definitionSchema);
|
|
287
|
-
const clusterConfig = Object.assign(Object.assign({},
|
|
288
|
-
? newCluster.deposit_amounts
|
|
289
|
-
: ['32000000000'] });
|
|
286
|
+
const validatedCluster = (0, ajv_js_1.validatePayload)(newCluster, schema_js_1.definitionSchema);
|
|
287
|
+
const clusterConfig = Object.assign(Object.assign({}, validatedCluster), { fork_version: this.fork_version, dkg_algorithm: constants_js_1.DKG_ALGORITHM, version: constants_js_1.CONFIG_VERSION, uuid: (0, uuid_1.v4)(), timestamp: new Date().toISOString(), threshold: Math.ceil((2 * validatedCluster.operators.length) / 3), num_validators: validatedCluster.validators.length });
|
|
290
288
|
try {
|
|
291
289
|
const address = yield this.signer.getAddress();
|
|
292
290
|
clusterConfig.creator = { address };
|
|
@@ -325,12 +323,12 @@ class Client extends base_js_1.Base {
|
|
|
325
323
|
if (!this.signer) {
|
|
326
324
|
throw new Error('Signer is required in acceptClusterDefinition');
|
|
327
325
|
}
|
|
328
|
-
(0, ajv_js_1.validatePayload)(operatorPayload, schema_js_1.operatorPayloadSchema);
|
|
326
|
+
const validatedPayload = (0, ajv_js_1.validatePayload)(operatorPayload, schema_js_1.operatorPayloadSchema);
|
|
329
327
|
try {
|
|
330
328
|
const address = yield this.signer.getAddress();
|
|
331
329
|
const operatorConfigSignature = yield this.signer.signTypedData((0, constants_js_1.Domain)(this.chainId), constants_js_1.OperatorConfigHashSigningTypes, { operator_config_hash: configHash });
|
|
332
|
-
const operatorENRSignature = yield this.signer.signTypedData((0, constants_js_1.Domain)(this.chainId), constants_js_1.EnrSigningTypes, { enr:
|
|
333
|
-
const operatorData = Object.assign(Object.assign({},
|
|
330
|
+
const operatorENRSignature = yield this.signer.signTypedData((0, constants_js_1.Domain)(this.chainId), constants_js_1.EnrSigningTypes, { enr: validatedPayload.enr });
|
|
331
|
+
const operatorData = Object.assign(Object.assign({}, validatedPayload), { address, enr_signature: operatorENRSignature, fork_version: this.fork_version });
|
|
334
332
|
const clusterDefinition = yield this.request(`/${constants_js_1.DEFAULT_BASE_VERSION}/definition/${configHash}`, {
|
|
335
333
|
method: 'PUT',
|
|
336
334
|
body: JSON.stringify(operatorData),
|
package/dist/cjs/src/schema.js
CHANGED
|
@@ -1,40 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.rewardsSplitterPayloadSchema = exports.totalSplitterPayloadSchema = exports.definitionSchema = exports.operatorPayloadSchema = void 0;
|
|
4
|
+
const ethers_1 = require("ethers");
|
|
4
5
|
const constants_1 = require("./constants");
|
|
6
|
+
const ajv_1 = require("./ajv");
|
|
5
7
|
exports.operatorPayloadSchema = {
|
|
6
8
|
type: 'object',
|
|
7
9
|
properties: {
|
|
8
|
-
version: {
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
enr: {
|
|
12
|
-
type: 'string',
|
|
13
|
-
},
|
|
10
|
+
version: { type: 'string' },
|
|
11
|
+
enr: { type: 'string' },
|
|
14
12
|
},
|
|
15
13
|
required: ['version', 'enr'],
|
|
16
14
|
};
|
|
17
15
|
exports.definitionSchema = {
|
|
18
16
|
type: 'object',
|
|
19
17
|
properties: {
|
|
20
|
-
name: {
|
|
21
|
-
type: 'string',
|
|
22
|
-
},
|
|
18
|
+
name: { type: 'string' },
|
|
23
19
|
operators: {
|
|
24
20
|
type: 'array',
|
|
25
21
|
minItems: 4,
|
|
26
|
-
uniqueItems: true,
|
|
27
22
|
items: {
|
|
28
23
|
type: 'object',
|
|
29
24
|
properties: {
|
|
30
25
|
address: {
|
|
31
26
|
type: 'string',
|
|
32
|
-
minLength: 42,
|
|
33
|
-
maxLength: 42,
|
|
34
27
|
},
|
|
35
28
|
},
|
|
36
29
|
required: ['address'],
|
|
37
30
|
},
|
|
31
|
+
validateUniqueAddresses: true,
|
|
38
32
|
},
|
|
39
33
|
validators: {
|
|
40
34
|
type: 'array',
|
|
@@ -55,12 +49,39 @@ exports.definitionSchema = {
|
|
|
55
49
|
},
|
|
56
50
|
},
|
|
57
51
|
deposit_amounts: {
|
|
58
|
-
type: 'array',
|
|
52
|
+
type: ['array', 'null'],
|
|
59
53
|
items: {
|
|
60
54
|
type: 'string',
|
|
61
55
|
pattern: '^[0-9]+$',
|
|
62
56
|
},
|
|
63
|
-
|
|
57
|
+
if: {
|
|
58
|
+
$data: '1/compounding',
|
|
59
|
+
},
|
|
60
|
+
then: {
|
|
61
|
+
items: {
|
|
62
|
+
enum: ajv_1.VALID_DEPOSIT_AMOUNTS,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
else: {
|
|
66
|
+
items: {
|
|
67
|
+
enum: ajv_1.VALID_NON_COMPOUNDING_AMOUNTS,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
default: null,
|
|
71
|
+
},
|
|
72
|
+
compounding: {
|
|
73
|
+
type: 'boolean',
|
|
74
|
+
default: true,
|
|
75
|
+
},
|
|
76
|
+
target_gas_limit: {
|
|
77
|
+
type: 'number',
|
|
78
|
+
minimum: 1,
|
|
79
|
+
default: 36000000,
|
|
80
|
+
},
|
|
81
|
+
consensus_protocol: {
|
|
82
|
+
type: 'string',
|
|
83
|
+
enum: ['qbft', ''],
|
|
84
|
+
default: '',
|
|
64
85
|
},
|
|
65
86
|
},
|
|
66
87
|
required: ['name', 'operators', 'validators'],
|
|
@@ -77,9 +98,7 @@ exports.totalSplitterPayloadSchema = {
|
|
|
77
98
|
type: 'string',
|
|
78
99
|
pattern: '^0x[a-fA-F0-9]{40}$',
|
|
79
100
|
},
|
|
80
|
-
percentAllocation: {
|
|
81
|
-
type: 'number',
|
|
82
|
-
},
|
|
101
|
+
percentAllocation: { type: 'number' },
|
|
83
102
|
},
|
|
84
103
|
required: ['account', 'percentAllocation'],
|
|
85
104
|
},
|
|
@@ -87,29 +106,37 @@ exports.totalSplitterPayloadSchema = {
|
|
|
87
106
|
ObolRAFSplit: {
|
|
88
107
|
type: 'number',
|
|
89
108
|
minimum: constants_1.DEFAULT_RETROACTIVE_FUNDING_TOTAL_SPLIT,
|
|
109
|
+
default: constants_1.DEFAULT_RETROACTIVE_FUNDING_TOTAL_SPLIT,
|
|
90
110
|
},
|
|
91
111
|
distributorFee: {
|
|
92
112
|
type: 'number',
|
|
93
113
|
maximum: 10,
|
|
94
114
|
multipleOf: 0.01,
|
|
115
|
+
default: 0,
|
|
95
116
|
},
|
|
96
117
|
controllerAddress: {
|
|
97
118
|
type: 'string',
|
|
98
119
|
pattern: '^0x[a-fA-F0-9]{40}$',
|
|
120
|
+
default: ethers_1.ZeroAddress,
|
|
99
121
|
},
|
|
100
|
-
validateSplitRecipients: true,
|
|
101
122
|
},
|
|
123
|
+
validateTotalSplitRecipients: true,
|
|
102
124
|
required: ['splitRecipients'],
|
|
103
125
|
};
|
|
104
|
-
exports.rewardsSplitterPayloadSchema =
|
|
126
|
+
exports.rewardsSplitterPayloadSchema = {
|
|
127
|
+
type: 'object',
|
|
128
|
+
properties: Object.assign(Object.assign({}, exports.totalSplitterPayloadSchema.properties), { ObolRAFSplit: {
|
|
105
129
|
type: 'number',
|
|
106
130
|
minimum: constants_1.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT,
|
|
131
|
+
default: constants_1.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT,
|
|
107
132
|
}, recoveryAddress: {
|
|
108
133
|
type: 'string',
|
|
109
134
|
pattern: '^0x[a-fA-F0-9]{40}$',
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}, principalRecipient: {
|
|
135
|
+
default: ethers_1.ZeroAddress,
|
|
136
|
+
}, etherAmount: { type: 'number' }, principalRecipient: {
|
|
113
137
|
type: 'string',
|
|
114
138
|
pattern: '^0x[a-fA-F0-9]{40}$',
|
|
115
|
-
} }),
|
|
139
|
+
} }),
|
|
140
|
+
validateRewardsSplitRecipients: true,
|
|
141
|
+
required: ['splitRecipients', 'principalRecipient', 'etherAmount'],
|
|
142
|
+
};
|
package/dist/cjs/src/services.js
CHANGED
|
@@ -14,15 +14,16 @@ const common_js_1 = require("./verification/common.js");
|
|
|
14
14
|
/**
|
|
15
15
|
* Verifies Cluster Lock's validity.
|
|
16
16
|
* @param lock - cluster lock
|
|
17
|
+
* @param safeRpcUrl - optional safeRpcUrl for safe wallet verification
|
|
17
18
|
* @returns {Promise<{ result: boolean }> } boolean result to indicate if lock is valid
|
|
18
19
|
* @throws on missing keys or values.
|
|
19
20
|
*
|
|
20
21
|
* An example of how to use validateClusterLock:
|
|
21
22
|
* [validateClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L127)
|
|
22
23
|
*/
|
|
23
|
-
const validateClusterLock = (lock) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
const validateClusterLock = (lock, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
25
|
try {
|
|
25
|
-
const isLockValid = yield (0, common_js_1.isValidClusterLock)(lock);
|
|
26
|
+
const isLockValid = yield (0, common_js_1.isValidClusterLock)(lock, safeRpcUrl);
|
|
26
27
|
return isLockValid;
|
|
27
28
|
}
|
|
28
29
|
catch (err) {
|
package/dist/cjs/src/utils.js
CHANGED
|
@@ -67,11 +67,11 @@ const isContractAvailable = (contractAddress, provider, bytecode) => __awaiter(v
|
|
|
67
67
|
return !!code && code !== '0x' && code !== '0x0';
|
|
68
68
|
});
|
|
69
69
|
exports.isContractAvailable = isContractAvailable;
|
|
70
|
-
const getProvider = (chainId) => {
|
|
71
|
-
const
|
|
72
|
-
if (!
|
|
70
|
+
const getProvider = (chainId, rpcUrl) => {
|
|
71
|
+
const resolvedRpcUrl = rpcUrl !== null && rpcUrl !== void 0 ? rpcUrl : constants_1.PROVIDER_MAP[chainId];
|
|
72
|
+
if (chainId && (!resolvedRpcUrl || resolvedRpcUrl === 'undefined')) {
|
|
73
73
|
throw new Error(`No provider configured for ${types_1.FORK_NAMES[chainId]}`);
|
|
74
74
|
}
|
|
75
|
-
return new ethers_1.ethers.JsonRpcProvider(
|
|
75
|
+
return new ethers_1.ethers.JsonRpcProvider(resolvedRpcUrl);
|
|
76
76
|
};
|
|
77
77
|
exports.getProvider = getProvider;
|
|
@@ -131,7 +131,7 @@ const clusterLockHash = (clusterLock) => {
|
|
|
131
131
|
exports.clusterLockHash = clusterLockHash;
|
|
132
132
|
// Lock verification
|
|
133
133
|
// cluster-definition signatures verification
|
|
134
|
-
const validatePOSTConfigHashSigner = (address, signature, configHash, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
134
|
+
const validatePOSTConfigHashSigner = (address, signature, configHash, chainId, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
135
135
|
try {
|
|
136
136
|
const data = (0, constants_js_1.signCreatorConfigHashPayload)({ creator_config_hash: configHash }, chainId);
|
|
137
137
|
return yield (0, signature_validator_js_1.validateAddressSignature)({
|
|
@@ -139,13 +139,14 @@ const validatePOSTConfigHashSigner = (address, signature, configHash, chainId) =
|
|
|
139
139
|
token: signature,
|
|
140
140
|
data,
|
|
141
141
|
chainId,
|
|
142
|
+
safeRpcUrl,
|
|
142
143
|
});
|
|
143
144
|
}
|
|
144
145
|
catch (err) {
|
|
145
146
|
throw err;
|
|
146
147
|
}
|
|
147
148
|
});
|
|
148
|
-
const validatePUTConfigHashSigner = (address, signature, configHash, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
|
+
const validatePUTConfigHashSigner = (address, signature, configHash, chainId, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
150
|
try {
|
|
150
151
|
const data = (0, constants_js_1.signOperatorConfigHashPayload)({ operator_config_hash: configHash }, chainId);
|
|
151
152
|
return yield (0, signature_validator_js_1.validateAddressSignature)({
|
|
@@ -153,13 +154,14 @@ const validatePUTConfigHashSigner = (address, signature, configHash, chainId) =>
|
|
|
153
154
|
token: signature,
|
|
154
155
|
data,
|
|
155
156
|
chainId,
|
|
157
|
+
safeRpcUrl,
|
|
156
158
|
});
|
|
157
159
|
}
|
|
158
160
|
catch (err) {
|
|
159
161
|
throw err;
|
|
160
162
|
}
|
|
161
163
|
});
|
|
162
|
-
const validateEnrSigner = (address, signature, payload, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
164
|
+
const validateEnrSigner = (address, signature, payload, chainId, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
163
165
|
try {
|
|
164
166
|
const data = (0, constants_js_1.signEnrPayload)({ enr: payload }, chainId);
|
|
165
167
|
return yield (0, signature_validator_js_1.validateAddressSignature)({
|
|
@@ -167,18 +169,19 @@ const validateEnrSigner = (address, signature, payload, chainId) => __awaiter(vo
|
|
|
167
169
|
token: signature,
|
|
168
170
|
data,
|
|
169
171
|
chainId,
|
|
172
|
+
safeRpcUrl,
|
|
170
173
|
});
|
|
171
174
|
}
|
|
172
175
|
catch (err) {
|
|
173
176
|
throw err;
|
|
174
177
|
}
|
|
175
178
|
});
|
|
176
|
-
const verifyDefinitionSignatures = (clusterDefinition, definitionType) => __awaiter(void 0, void 0, void 0, function* () {
|
|
179
|
+
const verifyDefinitionSignatures = (clusterDefinition, definitionType, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
177
180
|
if (definitionType === constants_js_1.DefinitionFlow.Charon) {
|
|
178
181
|
return true;
|
|
179
182
|
}
|
|
180
183
|
else {
|
|
181
|
-
const isPOSTConfigHashSignerValid = yield validatePOSTConfigHashSigner(clusterDefinition.creator.address, clusterDefinition.creator.config_signature, clusterDefinition.config_hash, types_js_1.FORK_MAPPING[clusterDefinition.fork_version]);
|
|
184
|
+
const isPOSTConfigHashSignerValid = yield validatePOSTConfigHashSigner(clusterDefinition.creator.address, clusterDefinition.creator.config_signature, clusterDefinition.config_hash, types_js_1.FORK_MAPPING[clusterDefinition.fork_version], safeRpcUrl);
|
|
182
185
|
if (!isPOSTConfigHashSignerValid) {
|
|
183
186
|
return false;
|
|
184
187
|
}
|
|
@@ -186,8 +189,8 @@ const verifyDefinitionSignatures = (clusterDefinition, definitionType) => __awai
|
|
|
186
189
|
return true;
|
|
187
190
|
}
|
|
188
191
|
for (const operator of clusterDefinition.operators) {
|
|
189
|
-
const isPUTConfigHashSignerValid = yield validatePUTConfigHashSigner(operator.address, operator.config_signature, clusterDefinition.config_hash, types_js_1.FORK_MAPPING[clusterDefinition.fork_version]);
|
|
190
|
-
const isENRSignerValid = yield validateEnrSigner(operator.address, operator.enr_signature, operator.enr, types_js_1.FORK_MAPPING[clusterDefinition.fork_version]);
|
|
192
|
+
const isPUTConfigHashSignerValid = yield validatePUTConfigHashSigner(operator.address, operator.config_signature, clusterDefinition.config_hash, types_js_1.FORK_MAPPING[clusterDefinition.fork_version], safeRpcUrl);
|
|
193
|
+
const isENRSignerValid = yield validateEnrSigner(operator.address, operator.enr_signature, operator.enr, types_js_1.FORK_MAPPING[clusterDefinition.fork_version], safeRpcUrl);
|
|
191
194
|
if (!isPUTConfigHashSignerValid || !isENRSignerValid) {
|
|
192
195
|
return false;
|
|
193
196
|
}
|
|
@@ -322,13 +325,13 @@ const verifyLockData = (clusterLock) => __awaiter(void 0, void 0, void 0, functi
|
|
|
322
325
|
}
|
|
323
326
|
return false;
|
|
324
327
|
});
|
|
325
|
-
const isValidClusterLock = (clusterLock) => __awaiter(void 0, void 0, void 0, function* () {
|
|
328
|
+
const isValidClusterLock = (clusterLock, safeRpcUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
326
329
|
try {
|
|
327
330
|
const definitionType = (0, utils_js_1.definitionFlow)(clusterLock.cluster_definition);
|
|
328
331
|
if (definitionType == null) {
|
|
329
332
|
return false;
|
|
330
333
|
}
|
|
331
|
-
const isValidDefinitionData = yield verifyDefinitionSignatures(clusterLock.cluster_definition, definitionType);
|
|
334
|
+
const isValidDefinitionData = yield verifyDefinitionSignatures(clusterLock.cluster_definition, definitionType, safeRpcUrl);
|
|
332
335
|
if (!isValidDefinitionData) {
|
|
333
336
|
return false;
|
|
334
337
|
}
|