@obolnetwork/obol-sdk 2.8.0 → 2.9.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 (40) hide show
  1. package/dist/cjs/package.json +2 -4
  2. package/dist/cjs/src/abi/splitV2FactoryAbi.js +420 -0
  3. package/dist/cjs/src/ajv.js +24 -0
  4. package/dist/cjs/src/bytecodes.js +3 -1
  5. package/dist/cjs/src/constants.js +24 -16
  6. package/dist/cjs/src/index.js +10 -10
  7. package/dist/cjs/src/schema.js +29 -3
  8. package/dist/cjs/src/splits/splitHelpers.js +100 -109
  9. package/dist/cjs/src/splits/splits.js +77 -16
  10. package/dist/cjs/test/client/ajv.spec.js +32 -0
  11. package/dist/cjs/test/splits/splits.spec.js +76 -2
  12. package/dist/esm/package.json +2 -4
  13. package/dist/esm/src/abi/splitV2FactoryAbi.js +417 -0
  14. package/dist/esm/src/ajv.js +24 -0
  15. package/dist/esm/src/bytecodes.js +2 -0
  16. package/dist/esm/src/constants.js +25 -17
  17. package/dist/esm/src/index.js +10 -10
  18. package/dist/esm/src/schema.js +28 -2
  19. package/dist/esm/src/splits/splitHelpers.js +101 -110
  20. package/dist/esm/src/splits/splits.js +79 -18
  21. package/dist/esm/test/client/ajv.spec.js +33 -1
  22. package/dist/esm/test/splits/splits.spec.js +77 -3
  23. package/dist/types/src/abi/splitV2FactoryAbi.d.ts +60 -0
  24. package/dist/types/src/bytecodes.d.ts +2 -0
  25. package/dist/types/src/exits/verificationHelpers.d.ts +1 -0
  26. package/dist/types/src/schema.d.ts +30 -3
  27. package/dist/types/src/splits/splitHelpers.d.ts +17 -3
  28. package/dist/types/src/splits/splits.d.ts +28 -1
  29. package/dist/types/src/types.d.ts +21 -6
  30. package/dist/types/src/verification/common.d.ts +1 -0
  31. package/package.json +2 -4
  32. package/src/abi/splitV2FactoryAbi.ts +417 -0
  33. package/src/ajv.ts +33 -0
  34. package/src/bytecodes.ts +4 -0
  35. package/src/constants.ts +26 -16
  36. package/src/index.ts +14 -14
  37. package/src/schema.ts +29 -2
  38. package/src/splits/splitHelpers.ts +169 -124
  39. package/src/splits/splits.ts +115 -17
  40. package/src/types.ts +24 -6
@@ -4,6 +4,7 @@ import {
4
4
  isSplitV2Deployed,
5
5
  deployOVMContract,
6
6
  deployOVMAndSplitV2,
7
+ requestWithdrawalFromOVM,
7
8
  } from './splitHelpers';
8
9
  import {
9
10
  CHAIN_CONFIGURATION,
@@ -14,6 +15,7 @@ import {
14
15
  import {
15
16
  ovmRewardsSplitPayloadSchema,
16
17
  ovmTotalSplitPayloadSchema,
18
+ ovmRequestWithdrawalPayloadSchema,
17
19
  } from '../schema';
18
20
  import { validatePayload } from '../ajv';
19
21
  import { isContractAvailable } from '../utils';
@@ -23,6 +25,7 @@ import {
23
25
  type SignerType,
24
26
  type OVMRewardsSplitPayload,
25
27
  type OVMTotalSplitPayload,
28
+ type OVMRequestWithdrawalPayload,
26
29
  } from '../types';
27
30
 
28
31
  /**
@@ -87,7 +90,7 @@ export class ObolSplits {
87
90
  }
88
91
 
89
92
  const chainConfig = CHAIN_CONFIGURATION[this.chainId];
90
- if (!chainConfig?.OVM_FACTORY_ADDRESS) {
93
+ if (!chainConfig?.OVM_FACTORY_CONTRACT) {
91
94
  throw new Error(
92
95
  `OVM contract factory is not configured for chain ${this.chainId}`,
93
96
  );
@@ -98,28 +101,53 @@ export class ObolSplits {
98
101
  'Provider is required to check OVM factory contract availability',
99
102
  );
100
103
  }
101
-
102
- const ovmFactoryConfig = chainConfig.OVM_FACTORY_ADDRESS;
103
- if (!ovmFactoryConfig?.address || !ovmFactoryConfig?.bytecode) {
104
+ const ovmFactoryConfig = chainConfig.OVM_FACTORY_CONTRACT;
105
+ const splitV2FactoryConfig = chainConfig.SPLIT_V2_FACTORY_CONTRACT;
106
+ const multiCallConfig = chainConfig.MULTICALL_CONTRACT;
107
+
108
+ if (
109
+ !ovmFactoryConfig?.address ||
110
+ !ovmFactoryConfig?.bytecode ||
111
+ !splitV2FactoryConfig?.address ||
112
+ !splitV2FactoryConfig?.bytecode ||
113
+ !multiCallConfig?.address ||
114
+ !multiCallConfig?.bytecode
115
+ ) {
104
116
  throw new Error(
105
- `OVM factory contract configuration is incomplete for chain ${this.chainId}`,
117
+ `Contracts configuration is incomplete for chain ${this.chainId}`,
106
118
  );
107
119
  }
108
120
 
109
- const checkOVMFactoryAddress = await isContractAvailable(
121
+ const checkOVMFactoryContract = await isContractAvailable(
110
122
  ovmFactoryConfig.address,
111
123
  this.provider,
112
124
  ovmFactoryConfig.bytecode,
113
125
  );
114
126
 
115
- if (!checkOVMFactoryAddress) {
127
+ const checkSplitV2FactoryContract = await isContractAvailable(
128
+ splitV2FactoryConfig.address,
129
+ this.provider,
130
+ splitV2FactoryConfig.bytecode,
131
+ );
132
+
133
+ const checkMultiCallContract = await isContractAvailable(
134
+ multiCallConfig.address,
135
+ this.provider,
136
+ multiCallConfig.bytecode,
137
+ );
138
+
139
+ if (
140
+ !checkOVMFactoryContract ||
141
+ !checkSplitV2FactoryContract ||
142
+ !checkMultiCallContract
143
+ ) {
116
144
  throw new Error(
117
- `OVM factory contract is not deployed or available on chain ${this.chainId}`,
145
+ `Splitter contract is not deployed or available on chain ${this.chainId}`,
118
146
  );
119
147
  }
120
148
 
121
149
  const retroActiveFundingRecipient = {
122
- address: chainConfig.RETROACTIVE_FUNDING_ADDRESS.address,
150
+ address: chainConfig.RETROACTIVE_FUNDING_CONTRACT.address,
123
151
  percentAllocation: DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT,
124
152
  };
125
153
 
@@ -228,7 +256,7 @@ export class ObolSplits {
228
256
  }
229
257
 
230
258
  const chainConfig = CHAIN_CONFIGURATION[this.chainId];
231
- if (!chainConfig?.OVM_FACTORY_ADDRESS) {
259
+ if (!chainConfig?.OVM_FACTORY_CONTRACT) {
232
260
  throw new Error(
233
261
  `OVM contract factory is not configured for chain ${this.chainId}`,
234
262
  );
@@ -240,27 +268,53 @@ export class ObolSplits {
240
268
  );
241
269
  }
242
270
 
243
- const ovmFactoryConfig = chainConfig.OVM_FACTORY_ADDRESS;
244
- if (!ovmFactoryConfig?.address || !ovmFactoryConfig?.bytecode) {
271
+ const ovmFactoryConfig = chainConfig.OVM_FACTORY_CONTRACT;
272
+ const splitV2FactoryConfig = chainConfig.SPLIT_V2_FACTORY_CONTRACT;
273
+ const multiCallConfig = chainConfig.MULTICALL_CONTRACT;
274
+
275
+ if (
276
+ !ovmFactoryConfig?.address ||
277
+ !ovmFactoryConfig?.bytecode ||
278
+ !splitV2FactoryConfig?.address ||
279
+ !splitV2FactoryConfig?.bytecode ||
280
+ !multiCallConfig?.address ||
281
+ !multiCallConfig?.bytecode
282
+ ) {
245
283
  throw new Error(
246
- `OVM factory contract configuration is incomplete for chain ${this.chainId}`,
284
+ `Contracts configuration is incomplete for chain ${this.chainId}`,
247
285
  );
248
286
  }
249
287
 
250
- const checkOVMFactoryAddress = await isContractAvailable(
288
+ const checkOVMFactoryContract = await isContractAvailable(
251
289
  ovmFactoryConfig.address,
252
290
  this.provider,
253
291
  ovmFactoryConfig.bytecode,
254
292
  );
255
293
 
256
- if (!checkOVMFactoryAddress) {
294
+ const checkSplitV2FactoryContract = await isContractAvailable(
295
+ splitV2FactoryConfig.address,
296
+ this.provider,
297
+ splitV2FactoryConfig.bytecode,
298
+ );
299
+
300
+ const checkMultiCallContract = await isContractAvailable(
301
+ multiCallConfig.address,
302
+ this.provider,
303
+ multiCallConfig.bytecode,
304
+ );
305
+
306
+ if (
307
+ !checkOVMFactoryContract ||
308
+ !checkSplitV2FactoryContract ||
309
+ !checkMultiCallContract
310
+ ) {
257
311
  throw new Error(
258
- `OVM factory contract is not deployed or available on chain ${this.chainId}`,
312
+ `Splitter contract is not deployed or available on chain ${this.chainId}`,
259
313
  );
260
314
  }
261
315
 
262
316
  const retroActiveFundingRecipient = {
263
- address: chainConfig.RETROACTIVE_FUNDING_ADDRESS.address,
317
+ address: chainConfig.RETROACTIVE_FUNDING_CONTRACT.address,
264
318
  percentAllocation: DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT,
265
319
  };
266
320
 
@@ -352,4 +406,48 @@ export class ObolSplits {
352
406
  };
353
407
  }
354
408
  }
409
+
410
+ /**
411
+ * Requests withdrawal from an OVM contract.
412
+ *
413
+ * This method allows requesting withdrawal of validator funds from an OVM contract.
414
+ * The withdrawal request includes OVM address, validator public keys and corresponding withdrawal amounts.
415
+ *
416
+ * @remarks
417
+ * **⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed
418
+ * and not pushed to version control.
419
+ *
420
+ * @param {OVMRequestWithdrawalPayload} payload - Data needed to request withdrawal
421
+ * @returns {Promise<{txHash: string}>} Transaction hash of the withdrawal request
422
+ * @throws Will throw an error if the signer is not provided, OVM address is invalid, or the request fails
423
+ *
424
+ * An example of how to use requestWithdrawal:
425
+ * ```typescript
426
+ * const result = await client.splits.requestWithdrawal({
427
+ * ovmAddress: '0x1234567890123456789012345678901234567890',
428
+ * pubKeys: ['0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456'],
429
+ * amounts: ['32000000000'] // 32 ETH in gwei
430
+ * });
431
+ * console.log('Withdrawal requested:', result.txHash);
432
+ * ```
433
+ */
434
+ async requestWithdrawal(
435
+ payload: OVMRequestWithdrawalPayload,
436
+ ): Promise<{ txHash: string }> {
437
+ if (!this.signer) {
438
+ throw new Error('Signer is required in requestWithdrawal');
439
+ }
440
+ // [TBD] need to move ovm verification to sdk method and use it here
441
+ const validatedPayload = validatePayload<OVMRequestWithdrawalPayload>(
442
+ payload,
443
+ ovmRequestWithdrawalPayloadSchema,
444
+ );
445
+
446
+ return await requestWithdrawalFromOVM({
447
+ ovmAddress: validatedPayload.ovmAddress,
448
+ pubKeys: validatedPayload.pubKeys,
449
+ amounts: validatedPayload.amounts,
450
+ signer: this.signer,
451
+ });
452
+ }
355
453
  }
package/src/types.ts CHANGED
@@ -578,28 +578,46 @@ export type OVMArgs = {
578
578
  };
579
579
 
580
580
  export type ChainConfig = {
581
- SPLITMAIN_ADDRESS: {
581
+ SPLITMAIN_CONTRACT: {
582
582
  address: string;
583
583
  bytecode: string;
584
584
  };
585
- MULTICALL_ADDRESS: {
585
+ MULTICALL_CONTRACT: {
586
586
  address: string;
587
587
  bytecode: string;
588
588
  };
589
- OWR_FACTORY_ADDRESS: {
589
+ OWR_FACTORY_CONTRACT: {
590
590
  address: string;
591
591
  bytecode: string;
592
592
  };
593
- RETROACTIVE_FUNDING_ADDRESS: {
593
+ RETROACTIVE_FUNDING_CONTRACT: {
594
594
  address: string;
595
595
  bytecode: string;
596
596
  };
597
- OVM_FACTORY_ADDRESS?: {
597
+ OVM_FACTORY_CONTRACT?: {
598
598
  address: string;
599
599
  bytecode: string;
600
600
  };
601
- WAREHOUSE_ADDRESS?: {
601
+ WAREHOUSE_CONTRACT?: {
602
602
  address: string;
603
603
  bytecode: string;
604
604
  };
605
+ SPLIT_V2_FACTORY_CONTRACT?: {
606
+ address: string;
607
+ bytecode: string;
608
+ };
609
+ };
610
+
611
+ /**
612
+ * Payload for requesting withdrawal from OVM contract
613
+ */
614
+ export type OVMRequestWithdrawalPayload = {
615
+ /** OVM contract address */
616
+ ovmAddress: string;
617
+
618
+ /** Array of validator public keys in bytes format */
619
+ pubKeys: string[];
620
+
621
+ /** Array of withdrawal amounts in gwei (uint64) as strings */
622
+ amounts: string[];
605
623
  };