@obolnetwork/obol-sdk 2.5.0 → 2.6.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.
Files changed (59) hide show
  1. package/dist/cjs/package.json +3 -3
  2. package/dist/cjs/src/constants.js +13 -1
  3. package/dist/cjs/src/exits/ethUtils.js +57 -0
  4. package/dist/cjs/src/exits/exit.js +420 -0
  5. package/dist/cjs/src/exits/verificationHelpers.js +86 -0
  6. package/dist/cjs/src/{incentiveHelpers.js → incentives/incentiveHelpers.js} +1 -1
  7. package/dist/cjs/src/{incentives.js → incentives/incentives.js} +3 -3
  8. package/dist/cjs/src/index.js +22 -4
  9. package/dist/cjs/src/schema.js +1 -1
  10. package/dist/cjs/src/splits/splitHelpers.js +327 -0
  11. package/dist/cjs/src/types.js +1 -0
  12. package/dist/cjs/test/exit/ethUtils.spec.js +83 -0
  13. package/dist/cjs/test/exit/exit.spec.js +328 -0
  14. package/dist/cjs/test/exit/verificationHelpers.spec.js +68 -0
  15. package/dist/cjs/test/{incentives.test.js → incentives/incentives.spec.js} +4 -4
  16. package/dist/esm/package.json +3 -3
  17. package/dist/esm/src/constants.js +12 -0
  18. package/dist/esm/src/exits/ethUtils.js +52 -0
  19. package/dist/esm/src/exits/exit.js +393 -0
  20. package/dist/esm/src/exits/verificationHelpers.js +81 -0
  21. package/dist/esm/src/{incentiveHelpers.js → incentives/incentiveHelpers.js} +1 -1
  22. package/dist/esm/src/{incentives.js → incentives/incentives.js} +3 -3
  23. package/dist/esm/src/index.js +20 -3
  24. package/dist/esm/src/schema.js +1 -1
  25. package/dist/esm/src/splits/splitHelpers.js +317 -0
  26. package/dist/esm/src/types.js +1 -0
  27. package/dist/esm/test/exit/ethUtils.spec.js +81 -0
  28. package/dist/esm/test/exit/exit.spec.js +303 -0
  29. package/dist/esm/test/exit/verificationHelpers.spec.js +66 -0
  30. package/dist/esm/test/{incentives.test.js → incentives/incentives.spec.js} +4 -4
  31. package/dist/types/src/constants.d.ts +5 -0
  32. package/dist/types/src/exits/ethUtils.d.ts +13 -0
  33. package/dist/types/src/exits/exit.d.ts +180 -0
  34. package/dist/types/src/exits/verificationHelpers.d.ts +20 -0
  35. package/dist/types/src/{incentiveHelpers.d.ts → incentives/incentiveHelpers.d.ts} +1 -1
  36. package/dist/types/src/{incentives.d.ts → incentives/incentives.d.ts} +1 -1
  37. package/dist/types/src/index.d.ts +16 -2
  38. package/dist/types/src/{splitHelpers.d.ts → splits/splitHelpers.d.ts} +1 -1
  39. package/dist/types/src/types.d.ts +98 -0
  40. package/dist/types/test/exit/verificationHelpers.spec.d.ts +1 -0
  41. package/dist/types/test/incentives/incentives.spec.d.ts +1 -0
  42. package/package.json +3 -3
  43. package/src/constants.ts +13 -0
  44. package/src/exits/ethUtils.ts +49 -0
  45. package/src/exits/exit.ts +564 -0
  46. package/src/exits/verificationHelpers.ts +110 -0
  47. package/src/{incentiveHelpers.ts → incentives/incentiveHelpers.ts} +2 -2
  48. package/src/{incentives.ts → incentives/incentives.ts} +3 -3
  49. package/src/index.ts +29 -3
  50. package/src/schema.ts +1 -1
  51. package/src/splits/splitHelpers.ts +557 -0
  52. package/src/types.ts +123 -0
  53. package/dist/cjs/src/splitHelpers.js +0 -187
  54. package/dist/cjs/test/methods.test.js +0 -418
  55. package/dist/esm/src/splitHelpers.js +0 -177
  56. package/dist/esm/test/methods.test.js +0 -393
  57. package/src/splitHelpers.ts +0 -355
  58. /package/dist/types/test/{incentives.test.d.ts → exit/ethUtils.spec.d.ts} +0 -0
  59. /package/dist/types/test/{methods.test.d.ts → exit/exit.spec.d.ts} +0 -0
@@ -23,7 +23,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
23
23
  });
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.Client = exports.Incentives = void 0;
26
+ exports.Client = exports.Exit = exports.Incentives = void 0;
27
27
  const uuid_1 = require("uuid");
28
28
  const base_js_1 = require("./base.js");
29
29
  const constants_js_1 = require("./constants.js");
@@ -31,16 +31,19 @@ const errors_js_1 = require("./errors.js");
31
31
  const common_js_1 = require("./verification/common.js");
32
32
  const ajv_js_1 = require("./ajv.js");
33
33
  const schema_js_1 = require("./schema.js");
34
- const splitHelpers_js_1 = require("./splitHelpers.js");
34
+ const splitHelpers_js_1 = require("./splits/splitHelpers.js");
35
35
  const utils_js_1 = require("./utils.js");
36
- const incentives_js_1 = require("./incentives.js");
36
+ const incentives_js_1 = require("./incentives/incentives.js");
37
+ const exit_js_1 = require("./exits/exit.js");
37
38
  __exportStar(require("./types.js"), exports);
38
39
  __exportStar(require("./services.js"), exports);
39
40
  __exportStar(require("./verification/signature-validator.js"), exports);
40
41
  __exportStar(require("./verification/common.js"), exports);
41
42
  __exportStar(require("./constants.js"), exports);
42
- var incentives_js_2 = require("./incentives.js");
43
+ var incentives_js_2 = require("./incentives/incentives.js");
43
44
  Object.defineProperty(exports, "Incentives", { enumerable: true, get: function () { return incentives_js_2.Incentives; } });
45
+ var exit_js_2 = require("./exits/exit.js");
46
+ Object.defineProperty(exports, "Exit", { enumerable: true, get: function () { return exit_js_2.Exit; } });
44
47
  /**
45
48
  * Obol sdk Client can be used for creating, managing and activating distributed validators.
46
49
  */
@@ -62,6 +65,7 @@ class Client extends base_js_1.Base {
62
65
  this.provider =
63
66
  provider !== null && provider !== void 0 ? provider : (signer && 'provider' in signer ? signer.provider : undefined);
64
67
  this.incentives = new incentives_js_1.Incentives(this.signer, this.chainId, this.request.bind(this), this.provider);
68
+ this.exit = new exit_js_1.Exit(this.chainId, this.provider);
65
69
  }
66
70
  /**
67
71
  * Accepts Obol terms and conditions to be able to create or update data.
@@ -375,5 +379,19 @@ class Client extends base_js_1.Base {
375
379
  return lock;
376
380
  });
377
381
  }
382
+ /**
383
+ * @param lockHash - The configuration hash in cluster-definition
384
+ * @returns {Promise<ClusterLock>} The matched cluster details (lock) from DB
385
+ * @throws On not found cluster definition or lock.
386
+ *
387
+ */
388
+ getClusterLockByHash(lockHash) {
389
+ return __awaiter(this, void 0, void 0, function* () {
390
+ const lock = yield this.request(`/${constants_js_1.DEFAULT_BASE_VERSION}/lock/${lockHash}`, {
391
+ method: 'GET',
392
+ });
393
+ return lock;
394
+ });
395
+ }
378
396
  }
379
397
  exports.Client = Client;
@@ -71,7 +71,7 @@ exports.definitionSchema = {
71
71
  },
72
72
  compounding: {
73
73
  type: 'boolean',
74
- default: true,
74
+ default: false,
75
75
  },
76
76
  target_gas_limit: {
77
77
  type: 'number',
@@ -0,0 +1,327 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.multicall = exports.getOWRTranches = exports.deploySplitterAndOWRContracts = exports.deploySplitterContract = exports.handleDeployOWRAndSplitter = exports.predictSplitterAddress = exports.formatSplitRecipients = void 0;
13
+ const ethers_1 = require("ethers");
14
+ const OWR_1 = require("../abi/OWR");
15
+ const SplitMain_1 = require("../abi/SplitMain");
16
+ const Multicall_1 = require("../abi/Multicall");
17
+ const constants_1 = require("../constants");
18
+ const splitMainContractInterface = new ethers_1.Interface(SplitMain_1.splitMainEthereumAbi);
19
+ const owrFactoryContractInterface = new ethers_1.Interface(OWR_1.OWRFactoryContract.abi);
20
+ const formatSplitRecipients = (recipients) => {
21
+ // Has to be sorted when passed
22
+ recipients.sort((a, b) => a.account.localeCompare(b.account));
23
+ const accounts = recipients.map(item => item.account);
24
+ const percentAllocations = recipients.map(recipient => {
25
+ const splitTostring = (recipient.percentAllocation * 1e4).toFixed(0);
26
+ return parseInt(splitTostring);
27
+ });
28
+ return { accounts, percentAllocations };
29
+ };
30
+ exports.formatSplitRecipients = formatSplitRecipients;
31
+ const predictSplitterAddress = ({ signer, accounts, percentAllocations, chainId, distributorFee, controllerAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
32
+ var _a, _b, _c;
33
+ try {
34
+ const splitMainContractInstance = new ethers_1.Contract(constants_1.CHAIN_CONFIGURATION[chainId].SPLITMAIN_ADDRESS.address, SplitMain_1.splitMainEthereumAbi, signer);
35
+ let predictedSplitterAddress;
36
+ if (controllerAddress === ethers_1.ZeroAddress) {
37
+ try {
38
+ predictedSplitterAddress =
39
+ yield splitMainContractInstance.predictImmutableSplitAddress(accounts, percentAllocations, distributorFee);
40
+ }
41
+ catch (error) {
42
+ throw new Error(`Failed to predict immutable splitter address: ${(_a = error.message) !== null && _a !== void 0 ? _a : 'Contract call failed'}`);
43
+ }
44
+ }
45
+ else {
46
+ try {
47
+ // It throws on deployed Immutable splitter
48
+ predictedSplitterAddress =
49
+ yield splitMainContractInstance.createSplit.staticCall(accounts, percentAllocations, distributorFee, controllerAddress);
50
+ }
51
+ catch (error) {
52
+ throw new Error(`Failed to predict mutable splitter address via static call: ${(_b = error.message) !== null && _b !== void 0 ? _b : 'Static call failed'}`);
53
+ }
54
+ }
55
+ return predictedSplitterAddress;
56
+ }
57
+ catch (error) {
58
+ // Re-throw if it's already our custom error
59
+ if (error.message.includes('Failed to predict')) {
60
+ throw error;
61
+ }
62
+ // Handle unexpected errors
63
+ throw new Error(`Unexpected error in predictSplitterAddress: ${(_c = error.message) !== null && _c !== void 0 ? _c : 'Unknown contract interaction error'}`);
64
+ }
65
+ });
66
+ exports.predictSplitterAddress = predictSplitterAddress;
67
+ const handleDeployOWRAndSplitter = ({ signer, isSplitterDeployed, predictedSplitterAddress, accounts, percentAllocations, etherAmount, principalRecipient, chainId, distributorFee, controllerAddress, recoveryAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
68
+ var _d, _e, _f;
69
+ try {
70
+ if (isSplitterDeployed) {
71
+ let owrAddress;
72
+ try {
73
+ owrAddress = yield createOWRContract({
74
+ owrArgs: {
75
+ principalRecipient,
76
+ amountOfPrincipalStake: etherAmount,
77
+ predictedSplitterAddress,
78
+ recoveryAddress,
79
+ },
80
+ signer,
81
+ chainId,
82
+ });
83
+ }
84
+ catch (error) {
85
+ throw new Error(`Failed to create OWR contract with existing splitter: ${(_d = error.message) !== null && _d !== void 0 ? _d : 'OWR contract creation failed'}`);
86
+ }
87
+ return {
88
+ withdrawal_address: owrAddress,
89
+ fee_recipient_address: predictedSplitterAddress,
90
+ };
91
+ }
92
+ else {
93
+ let owrAddress;
94
+ let splitterAddress;
95
+ try {
96
+ const result = yield (0, exports.deploySplitterAndOWRContracts)({
97
+ owrArgs: {
98
+ principalRecipient,
99
+ amountOfPrincipalStake: etherAmount,
100
+ predictedSplitterAddress,
101
+ recoveryAddress,
102
+ },
103
+ splitterArgs: {
104
+ accounts,
105
+ percentAllocations,
106
+ distributorFee,
107
+ controllerAddress,
108
+ },
109
+ signer,
110
+ chainId,
111
+ });
112
+ owrAddress = result.owrAddress;
113
+ splitterAddress = result.splitterAddress;
114
+ }
115
+ catch (error) {
116
+ throw new Error(`Failed to deploy both splitter and OWR contracts: ${(_e = error.message) !== null && _e !== void 0 ? _e : 'Multicall contract deployment failed'}`);
117
+ }
118
+ return {
119
+ withdrawal_address: owrAddress,
120
+ fee_recipient_address: splitterAddress,
121
+ };
122
+ }
123
+ }
124
+ catch (error) {
125
+ // Re-throw if it's already our custom error
126
+ if (error.message.includes('Failed to')) {
127
+ throw error;
128
+ }
129
+ // Handle unexpected errors
130
+ throw new Error(`Unexpected error in handleDeployOWRAndSplitter: ${(_f = error.message) !== null && _f !== void 0 ? _f : 'Unknown error during contract deployment orchestration'}`);
131
+ }
132
+ });
133
+ exports.handleDeployOWRAndSplitter = handleDeployOWRAndSplitter;
134
+ const createOWRContract = ({ owrArgs, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
135
+ var _g, _h, _j, _k, _l;
136
+ try {
137
+ const OWRFactoryInstance = new ethers_1.Contract(constants_1.CHAIN_CONFIGURATION[chainId].OWR_FACTORY_ADDRESS.address, OWR_1.OWRFactoryContract.abi, signer);
138
+ let tx;
139
+ try {
140
+ tx = yield OWRFactoryInstance.createOWRecipient(owrArgs.recoveryAddress, owrArgs.principalRecipient, owrArgs.predictedSplitterAddress, (0, ethers_1.parseEther)(owrArgs.amountOfPrincipalStake.toString()));
141
+ }
142
+ catch (error) {
143
+ throw new Error(`Failed to submit OWR contract creation transaction: ${(_g = error.message) !== null && _g !== void 0 ? _g : 'Transaction submission failed'}`);
144
+ }
145
+ let receipt;
146
+ try {
147
+ receipt = yield tx.wait();
148
+ }
149
+ catch (error) {
150
+ throw new Error(`OWR contract creation transaction failed or was reverted: ${(_h = error.message) !== null && _h !== void 0 ? _h : 'Transaction execution failed'}`);
151
+ }
152
+ if (!((_j = receipt === null || receipt === void 0 ? void 0 : receipt.logs) === null || _j === void 0 ? void 0 : _j.length)) {
153
+ throw new Error('OWR contract creation transaction succeeded but no events were emitted - unable to determine contract address');
154
+ }
155
+ const OWRAddressData = (_k = receipt.logs[0]) === null || _k === void 0 ? void 0 : _k.topics[1];
156
+ if (!OWRAddressData) {
157
+ throw new Error('OWR contract creation transaction succeeded but contract address could not be extracted from events');
158
+ }
159
+ const formattedOWRAddress = '0x' + OWRAddressData.slice(26, 66);
160
+ // Basic address validation
161
+ if (formattedOWRAddress.length !== 42 ||
162
+ !formattedOWRAddress.startsWith('0x')) {
163
+ throw new Error(`Invalid OWR contract address format: ${formattedOWRAddress}`);
164
+ }
165
+ return formattedOWRAddress;
166
+ }
167
+ catch (error) {
168
+ // Re-throw if it's already our custom error
169
+ if (error.message.includes('Failed to') ||
170
+ error.message.includes('OWR contract') ||
171
+ error.message.includes('Invalid OWR')) {
172
+ throw error;
173
+ }
174
+ // Handle unexpected errors
175
+ throw new Error(`Unexpected error in createOWRContract: ${(_l = error.message) !== null && _l !== void 0 ? _l : 'Unknown error during OWR contract creation'}`);
176
+ }
177
+ });
178
+ const deploySplitterContract = ({ signer, accounts, percentAllocations, chainId, distributorFee, controllerAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
179
+ var _m, _o, _p, _q, _r;
180
+ try {
181
+ const splitMainContractInstance = new ethers_1.Contract(constants_1.CHAIN_CONFIGURATION[chainId].SPLITMAIN_ADDRESS.address, SplitMain_1.splitMainEthereumAbi, signer);
182
+ let tx;
183
+ try {
184
+ tx = yield splitMainContractInstance.createSplit(accounts, percentAllocations, distributorFee, controllerAddress);
185
+ }
186
+ catch (error) {
187
+ throw new Error(`Failed to submit splitter contract creation transaction: ${(_m = error.message) !== null && _m !== void 0 ? _m : 'Transaction submission failed'}`);
188
+ }
189
+ let receipt;
190
+ try {
191
+ receipt = yield tx.wait();
192
+ }
193
+ catch (error) {
194
+ throw new Error(`Splitter contract creation transaction failed or was reverted: ${(_o = error.message) !== null && _o !== void 0 ? _o : 'Transaction execution failed'}`);
195
+ }
196
+ if (!((_p = receipt === null || receipt === void 0 ? void 0 : receipt.logs) === null || _p === void 0 ? void 0 : _p.length)) {
197
+ throw new Error('Splitter contract creation transaction succeeded but no events were emitted - unable to determine contract address');
198
+ }
199
+ const splitterAddressData = (_q = receipt.logs[0]) === null || _q === void 0 ? void 0 : _q.topics[1];
200
+ if (!splitterAddressData) {
201
+ throw new Error('Splitter contract creation transaction succeeded but contract address could not be extracted from events');
202
+ }
203
+ const formattedSplitterAddress = '0x' + splitterAddressData.slice(26, 66);
204
+ // Basic address validation
205
+ if (formattedSplitterAddress.length !== 42 ||
206
+ !formattedSplitterAddress.startsWith('0x')) {
207
+ throw new Error(`Invalid splitter contract address format: ${formattedSplitterAddress}`);
208
+ }
209
+ return formattedSplitterAddress;
210
+ }
211
+ catch (error) {
212
+ // Re-throw if it's already our custom error
213
+ if (error.message.includes('Failed to') ||
214
+ error.message.includes('Splitter contract') ||
215
+ error.message.includes('Invalid splitter')) {
216
+ throw error;
217
+ }
218
+ // Handle unexpected errors
219
+ throw new Error(`Unexpected error in deploySplitterContract: ${(_r = error.message) !== null && _r !== void 0 ? _r : 'Unknown error during splitter contract creation'}`);
220
+ }
221
+ });
222
+ exports.deploySplitterContract = deploySplitterContract;
223
+ const deploySplitterAndOWRContracts = ({ owrArgs, splitterArgs, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
224
+ var _s, _t;
225
+ const executeCalls = [];
226
+ const splitTxData = encodeCreateSplitTxData(splitterArgs.accounts, splitterArgs.percentAllocations, splitterArgs.distributorFee, splitterArgs.controllerAddress);
227
+ const owrTxData = encodeCreateOWRecipientTxData(owrArgs.recoveryAddress, owrArgs.principalRecipient, owrArgs.predictedSplitterAddress, owrArgs.amountOfPrincipalStake);
228
+ executeCalls.push({
229
+ target: constants_1.CHAIN_CONFIGURATION[chainId].SPLITMAIN_ADDRESS.address,
230
+ callData: splitTxData,
231
+ }, {
232
+ target: constants_1.CHAIN_CONFIGURATION[chainId].OWR_FACTORY_ADDRESS.address,
233
+ callData: owrTxData,
234
+ });
235
+ const multicallAddess = constants_1.CHAIN_CONFIGURATION[chainId].MULTICALL_ADDRESS.address;
236
+ const executeMultiCalls = yield (0, exports.multicall)(executeCalls, signer, multicallAddess);
237
+ const splitAddressData = (_s = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[0]) === null || _s === void 0 ? void 0 : _s.topics[1];
238
+ const formattedSplitterAddress = '0x' + (splitAddressData === null || splitAddressData === void 0 ? void 0 : splitAddressData.slice(26, 66));
239
+ const owrAddressData = (_t = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[1]) === null || _t === void 0 ? void 0 : _t.topics[1];
240
+ const formattedOwrAddress = '0x' + (owrAddressData === null || owrAddressData === void 0 ? void 0 : owrAddressData.slice(26, 66));
241
+ return {
242
+ owrAddress: formattedOwrAddress,
243
+ splitterAddress: formattedSplitterAddress,
244
+ };
245
+ });
246
+ exports.deploySplitterAndOWRContracts = deploySplitterAndOWRContracts;
247
+ const getOWRTranches = ({ owrAddress, signer, }) => __awaiter(void 0, void 0, void 0, function* () {
248
+ var _u, _v;
249
+ try {
250
+ const owrContract = new ethers_1.Contract(owrAddress, OWR_1.OWRContract.abi, signer);
251
+ let res;
252
+ try {
253
+ res = yield owrContract.getTranches();
254
+ }
255
+ catch (error) {
256
+ throw new Error(`Failed to call getTranches on OWR contract at ${owrAddress}: ${(_u = error.message) !== null && _u !== void 0 ? _u : 'Contract call failed'}`);
257
+ }
258
+ if (!res) {
259
+ throw new Error(`OWR contract at ${owrAddress} returned empty result for getTranches()`);
260
+ }
261
+ return {
262
+ principalRecipient: res.principalRecipient,
263
+ rewardRecipient: res.rewardRecipient,
264
+ amountOfPrincipalStake: res.amountOfPrincipalStake,
265
+ };
266
+ }
267
+ catch (error) {
268
+ // Re-throw if it's already our custom error
269
+ if (error.message.includes('Failed to') ||
270
+ error.message.includes('OWR contract')) {
271
+ throw error;
272
+ }
273
+ // Handle unexpected errors
274
+ throw new Error(`Unexpected error in getOWRTranches: ${(_v = error.message) !== null && _v !== void 0 ? _v : 'Unknown error while fetching OWR tranche data'}`);
275
+ }
276
+ });
277
+ exports.getOWRTranches = getOWRTranches;
278
+ const multicall = (calls, signer, multicallAddress) => __awaiter(void 0, void 0, void 0, function* () {
279
+ var _w, _x, _y;
280
+ try {
281
+ const multiCallContractInstance = new ethers_1.Contract(multicallAddress, Multicall_1.MultiCallContract.abi, signer);
282
+ let tx;
283
+ try {
284
+ tx = yield multiCallContractInstance.aggregate(calls);
285
+ }
286
+ catch (error) {
287
+ throw new Error(`Failed to submit multicall transaction: ${(_w = error.message) !== null && _w !== void 0 ? _w : 'Transaction submission failed'}`);
288
+ }
289
+ let receipt;
290
+ try {
291
+ receipt = yield tx.wait();
292
+ }
293
+ catch (error) {
294
+ throw new Error(`Multicall transaction failed or was reverted: ${(_x = error.message) !== null && _x !== void 0 ? _x : 'Transaction execution failed'}`);
295
+ }
296
+ if (!receipt) {
297
+ throw new Error('Multicall transaction succeeded but no receipt was returned');
298
+ }
299
+ return receipt;
300
+ }
301
+ catch (error) {
302
+ // Re-throw if it's already our custom error
303
+ if (error.message.includes('Failed to') ||
304
+ error.message.includes('Multicall transaction')) {
305
+ throw error;
306
+ }
307
+ // Handle unexpected errors
308
+ throw new Error(`Unexpected error in multicall: ${(_y = error.message) !== null && _y !== void 0 ? _y : 'Unknown error during multicall execution'}`);
309
+ }
310
+ });
311
+ exports.multicall = multicall;
312
+ const encodeCreateSplitTxData = (accounts, percentAllocations, distributorFee, controller) => {
313
+ return splitMainContractInterface.encodeFunctionData('createSplit', [
314
+ accounts,
315
+ percentAllocations,
316
+ distributorFee,
317
+ controller,
318
+ ]);
319
+ };
320
+ const encodeCreateOWRecipientTxData = (recoveryAddress, principalRecipient, rewardRecipient, amountOfPrincipalStake) => {
321
+ return owrFactoryContractInterface.encodeFunctionData('createOWRecipient', [
322
+ recoveryAddress,
323
+ principalRecipient,
324
+ rewardRecipient,
325
+ (0, ethers_1.parseEther)(amountOfPrincipalStake.toString()),
326
+ ]);
327
+ };
@@ -27,3 +27,4 @@ exports.FORK_NAMES = {
27
27
  [FORK_MAPPING['0x90000069']]: 'sepolia',
28
28
  [FORK_MAPPING['0x10000910']]: 'hoodi',
29
29
  };
30
+ // Add other SDK-specific types below or import from other type files
@@ -0,0 +1,83 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const ethUtils_1 = require("../../src/exits/ethUtils");
13
+ const constants_1 = require("../../src/constants");
14
+ describe('ethUtils', () => {
15
+ describe('getCapellaFork', () => {
16
+ Object.entries(constants_1.CAPELLA_FORK_MAPPING).forEach(([baseFork, expectedCapellaFork]) => {
17
+ it(`should return ${expectedCapellaFork} for base fork ${baseFork}`, () => __awaiter(void 0, void 0, void 0, function* () {
18
+ const result = yield (0, ethUtils_1.getCapellaFork)(baseFork);
19
+ expect(result).toBe(expectedCapellaFork);
20
+ }));
21
+ });
22
+ it('should return null for an unknown base fork version', () => __awaiter(void 0, void 0, void 0, function* () {
23
+ const result = yield (0, ethUtils_1.getCapellaFork)('0xUNKNOWNFORK');
24
+ expect(result).toBeNull();
25
+ }));
26
+ });
27
+ describe('getGenesisValidatorsRoot', () => {
28
+ const mockBeaconApiUrl = 'http://localhost:5052';
29
+ const mockGenesisRoot = '0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2';
30
+ beforeEach(() => {
31
+ // Reset fetch mock
32
+ global.fetch = jest.fn();
33
+ });
34
+ afterEach(() => {
35
+ jest.restoreAllMocks();
36
+ });
37
+ it('should fetch and return the genesis_validators_root successfully', () => __awaiter(void 0, void 0, void 0, function* () {
38
+ global.fetch.mockResolvedValueOnce({
39
+ json: () => __awaiter(void 0, void 0, void 0, function* () {
40
+ return ({
41
+ data: { genesis_validators_root: mockGenesisRoot },
42
+ });
43
+ }),
44
+ });
45
+ const result = yield (0, ethUtils_1.getGenesisValidatorsRoot)(mockBeaconApiUrl);
46
+ expect(result).toBe(mockGenesisRoot);
47
+ expect(global.fetch).toHaveBeenCalledTimes(1);
48
+ expect(global.fetch).toHaveBeenCalledWith(`${mockBeaconApiUrl}/eth/v1/beacon/genesis`, { method: 'GET' });
49
+ }));
50
+ it('should return null if the HTTP request fails (e.g., network error)', () => __awaiter(void 0, void 0, void 0, function* () {
51
+ global.fetch.mockRejectedValueOnce(new Error('Network error'));
52
+ yield expect((0, ethUtils_1.getGenesisValidatorsRoot)(mockBeaconApiUrl)).rejects.toThrow('Failed to fetch genesis validators root: Network error');
53
+ expect(global.fetch).toHaveBeenCalledTimes(1);
54
+ }));
55
+ it('should return null if the response data structure is invalid (missing genesis_validators_root)', () => __awaiter(void 0, void 0, void 0, function* () {
56
+ global.fetch.mockResolvedValueOnce({
57
+ json: () => __awaiter(void 0, void 0, void 0, function* () {
58
+ return ({
59
+ data: { some_other_field: 'value' },
60
+ });
61
+ }),
62
+ });
63
+ const result = yield (0, ethUtils_1.getGenesisValidatorsRoot)(mockBeaconApiUrl);
64
+ expect(result).toBeNull();
65
+ expect(global.fetch).toHaveBeenCalledTimes(1);
66
+ }));
67
+ it('should return null if the response data is missing', () => __awaiter(void 0, void 0, void 0, function* () {
68
+ global.fetch.mockResolvedValueOnce({
69
+ json: () => __awaiter(void 0, void 0, void 0, function* () { return ({}); }),
70
+ });
71
+ const result = yield (0, ethUtils_1.getGenesisValidatorsRoot)(mockBeaconApiUrl);
72
+ expect(result).toBeNull();
73
+ }));
74
+ it('should throw an error if fetch throws an error with a message', () => __awaiter(void 0, void 0, void 0, function* () {
75
+ global.fetch.mockRejectedValueOnce(new Error('Custom HTTP error'));
76
+ yield expect((0, ethUtils_1.getGenesisValidatorsRoot)(mockBeaconApiUrl)).rejects.toThrow('Failed to fetch genesis validators root: Custom HTTP error');
77
+ }));
78
+ it('should throw an error if fetch throws a non-Error object', () => __awaiter(void 0, void 0, void 0, function* () {
79
+ global.fetch.mockRejectedValueOnce('some string error');
80
+ yield expect((0, ethUtils_1.getGenesisValidatorsRoot)(mockBeaconApiUrl)).rejects.toThrow('Failed to fetch genesis validators root: some string error');
81
+ }));
82
+ });
83
+ });