@obolnetwork/obol-sdk 2.0.1 → 2.1.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 (49) hide show
  1. package/README.md +6 -0
  2. package/dist/cjs/package.json +1 -1
  3. package/dist/cjs/src/abi/Multicall.js +148 -0
  4. package/dist/cjs/src/abi/OWR.js +133 -0
  5. package/dist/cjs/src/abi/SplitMain.js +929 -0
  6. package/dist/cjs/src/ajv.js +17 -2
  7. package/dist/cjs/src/bytecodes.js +9 -0
  8. package/dist/cjs/src/constants.js +48 -1
  9. package/dist/cjs/src/index.js +146 -0
  10. package/dist/cjs/src/schema.js +52 -5
  11. package/dist/cjs/src/splitHelpers.js +177 -0
  12. package/dist/cjs/src/utils.js +22 -1
  13. package/dist/cjs/test/fixtures.js +1 -1
  14. package/dist/cjs/test/methods.test.js +215 -11
  15. package/dist/esm/package.json +1 -1
  16. package/dist/esm/src/abi/Multicall.js +145 -0
  17. package/dist/esm/src/abi/OWR.js +130 -0
  18. package/dist/esm/src/abi/SplitMain.js +926 -0
  19. package/dist/esm/src/ajv.js +17 -2
  20. package/dist/esm/src/bytecodes.js +6 -0
  21. package/dist/esm/src/constants.js +47 -0
  22. package/dist/esm/src/index.js +148 -2
  23. package/dist/esm/src/schema.js +51 -4
  24. package/dist/esm/src/splitHelpers.js +168 -0
  25. package/dist/esm/src/utils.js +19 -0
  26. package/dist/esm/test/fixtures.js +1 -1
  27. package/dist/esm/test/methods.test.js +193 -12
  28. package/dist/types/src/abi/Multicall.d.ts +35 -0
  29. package/dist/types/src/abi/OWR.d.ts +52 -0
  30. package/dist/types/src/abi/SplitMain.d.ts +1159 -0
  31. package/dist/types/src/bytecodes.d.ts +6 -0
  32. package/dist/types/src/constants.d.ts +25 -0
  33. package/dist/types/src/index.d.ts +29 -1
  34. package/dist/types/src/schema.d.ts +85 -4
  35. package/dist/types/src/splitHelpers.d.ts +62 -0
  36. package/dist/types/src/types.d.ts +39 -2
  37. package/dist/types/src/utils.d.ts +3 -0
  38. package/package.json +1 -1
  39. package/src/abi/Multicall.ts +145 -0
  40. package/src/abi/OWR.ts +130 -0
  41. package/src/abi/SplitMain.ts +927 -0
  42. package/src/ajv.ts +33 -2
  43. package/src/bytecodes.ts +12 -0
  44. package/src/constants.ts +59 -0
  45. package/src/index.ts +244 -2
  46. package/src/schema.ts +67 -4
  47. package/src/splitHelpers.ts +341 -0
  48. package/src/types.ts +49 -2
  49. package/src/utils.ts +21 -0
@@ -0,0 +1,168 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { Contract, Interface, parseEther, ZeroAddress, } from 'ethers';
11
+ import { OWRFactoryContract } from './abi/OWR';
12
+ import { splitMainEthereumAbi } from './abi/SplitMain';
13
+ import { MultiCallContract } from './abi/Multicall';
14
+ import { CHAIN_CONFIGURATION } from './constants';
15
+ const splitMainContractInterface = new Interface(splitMainEthereumAbi);
16
+ const owrFactoryContractInterface = new Interface(OWRFactoryContract.abi);
17
+ export const formatSplitRecipients = (recipients) => {
18
+ // Has to be sorted when passed
19
+ recipients.sort((a, b) => a.account.localeCompare(b.account));
20
+ const accounts = recipients.map(item => item.account);
21
+ const percentAllocations = recipients.map(recipient => {
22
+ const splitTostring = (recipient.percentAllocation * 1e4).toFixed(0);
23
+ return parseInt(splitTostring);
24
+ });
25
+ return { accounts, percentAllocations };
26
+ };
27
+ export const predictSplitterAddress = ({ signer, accounts, percentAllocations, chainId, distributorFee, controllerAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
28
+ try {
29
+ let predictedSplitterAddress;
30
+ const splitMainContractInstance = new Contract(CHAIN_CONFIGURATION[chainId].SPLITMAIN_ADDRESS.address, splitMainEthereumAbi, signer);
31
+ if (controllerAddress === ZeroAddress) {
32
+ predictedSplitterAddress =
33
+ yield splitMainContractInstance.predictImmutableSplitAddress(accounts, percentAllocations, distributorFee);
34
+ }
35
+ else {
36
+ // It throws on deployed Immutable splitter
37
+ predictedSplitterAddress =
38
+ yield splitMainContractInstance.createSplit.staticCall(accounts, percentAllocations, distributorFee, controllerAddress);
39
+ }
40
+ return predictedSplitterAddress;
41
+ }
42
+ catch (e) {
43
+ throw e;
44
+ }
45
+ });
46
+ export const handleDeployOWRAndSplitter = ({ signer, isSplitterDeployed, predictedSplitterAddress, accounts, percentAllocations, etherAmount, principalRecipient, chainId, distributorFee, controllerAddress, recoveryAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
47
+ try {
48
+ if (isSplitterDeployed) {
49
+ const owrAddress = yield createOWRContract({
50
+ owrArgs: {
51
+ principalRecipient,
52
+ amountOfPrincipalStake: etherAmount,
53
+ predictedSplitterAddress,
54
+ recoveryAddress,
55
+ },
56
+ signer,
57
+ chainId,
58
+ });
59
+ return {
60
+ withdrawal_address: owrAddress,
61
+ fee_recipient_address: predictedSplitterAddress,
62
+ };
63
+ }
64
+ else {
65
+ const { owrAddress, splitterAddress } = yield deploySplitterAndOWRContracts({
66
+ owrArgs: {
67
+ principalRecipient,
68
+ amountOfPrincipalStake: etherAmount,
69
+ predictedSplitterAddress,
70
+ recoveryAddress,
71
+ },
72
+ splitterArgs: {
73
+ accounts,
74
+ percentAllocations,
75
+ distributorFee,
76
+ controllerAddress,
77
+ },
78
+ signer,
79
+ chainId,
80
+ });
81
+ return {
82
+ withdrawal_address: owrAddress,
83
+ fee_recipient_address: splitterAddress,
84
+ };
85
+ }
86
+ }
87
+ catch (e) {
88
+ throw e;
89
+ }
90
+ });
91
+ const createOWRContract = ({ owrArgs, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
92
+ var _a;
93
+ try {
94
+ const OWRFactoryInstance = new Contract(CHAIN_CONFIGURATION[chainId].OWR_FACTORY_ADDRESS.address, OWRFactoryContract.abi, signer);
95
+ const tx = yield OWRFactoryInstance.createOWRecipient(owrArgs.recoveryAddress, owrArgs.principalRecipient, owrArgs.predictedSplitterAddress, parseEther(owrArgs.amountOfPrincipalStake.toString()));
96
+ const receipt = yield tx.wait();
97
+ const OWRAddressData = (_a = receipt === null || receipt === void 0 ? void 0 : receipt.logs[0]) === null || _a === void 0 ? void 0 : _a.topics[1];
98
+ const formattedOWRAddress = '0x' + (OWRAddressData === null || OWRAddressData === void 0 ? void 0 : OWRAddressData.slice(26, 66));
99
+ return formattedOWRAddress;
100
+ }
101
+ catch (e) {
102
+ throw e;
103
+ }
104
+ });
105
+ export const deploySplitterContract = ({ signer, accounts, percentAllocations, chainId, distributorFee, controllerAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
106
+ var _b;
107
+ try {
108
+ const splitMainContractInstance = new Contract(CHAIN_CONFIGURATION[chainId].SPLITMAIN_ADDRESS.address, splitMainEthereumAbi, signer);
109
+ const tx = yield splitMainContractInstance.createSplit(accounts, percentAllocations, distributorFee, controllerAddress);
110
+ const receipt = yield tx.wait();
111
+ const splitterAddressData = (_b = receipt === null || receipt === void 0 ? void 0 : receipt.logs[0]) === null || _b === void 0 ? void 0 : _b.topics[1];
112
+ const formattedSplitterAddress = '0x' + (splitterAddressData === null || splitterAddressData === void 0 ? void 0 : splitterAddressData.slice(26, 66));
113
+ return formattedSplitterAddress;
114
+ }
115
+ catch (e) {
116
+ throw e;
117
+ }
118
+ });
119
+ export const deploySplitterAndOWRContracts = ({ owrArgs, splitterArgs, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
120
+ var _c, _d;
121
+ const executeCalls = [];
122
+ try {
123
+ const splitTxData = encodeCreateSplitTxData(splitterArgs.accounts, splitterArgs.percentAllocations, splitterArgs.distributorFee, splitterArgs.controllerAddress);
124
+ const owrTxData = encodeCreateOWRecipientTxData(owrArgs.recoveryAddress, owrArgs.principalRecipient, owrArgs.predictedSplitterAddress, owrArgs.amountOfPrincipalStake);
125
+ executeCalls.push({
126
+ target: CHAIN_CONFIGURATION[chainId].SPLITMAIN_ADDRESS.address,
127
+ callData: splitTxData,
128
+ }, {
129
+ target: CHAIN_CONFIGURATION[chainId].OWR_FACTORY_ADDRESS.address,
130
+ callData: owrTxData,
131
+ });
132
+ const multicallAddess = CHAIN_CONFIGURATION[chainId].MULTICALL_ADDRESS.address;
133
+ const executeMultiCalls = yield multicall(executeCalls, signer, multicallAddess);
134
+ const splitAddressData = (_c = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[0]) === null || _c === void 0 ? void 0 : _c.topics[1];
135
+ const formattedSplitterAddress = '0x' + (splitAddressData === null || splitAddressData === void 0 ? void 0 : splitAddressData.slice(26, 66));
136
+ const owrAddressData = (_d = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[1]) === null || _d === void 0 ? void 0 : _d.topics[1];
137
+ const formattedOwrAddress = '0x' + (owrAddressData === null || owrAddressData === void 0 ? void 0 : owrAddressData.slice(26, 66));
138
+ return {
139
+ owrAddress: formattedOwrAddress,
140
+ splitterAddress: formattedSplitterAddress,
141
+ };
142
+ }
143
+ catch (e) {
144
+ throw e;
145
+ }
146
+ });
147
+ export const multicall = (calls, signer, multicallAddress) => __awaiter(void 0, void 0, void 0, function* () {
148
+ const multiCallContractInstance = new Contract(multicallAddress, MultiCallContract.abi, signer);
149
+ const tx = yield multiCallContractInstance.aggregate(calls);
150
+ const receipt = yield tx.wait();
151
+ return receipt;
152
+ });
153
+ const encodeCreateSplitTxData = (accounts, percentAllocations, distributorFee, controller) => {
154
+ return splitMainContractInterface.encodeFunctionData('createSplit', [
155
+ accounts,
156
+ percentAllocations,
157
+ distributorFee,
158
+ controller,
159
+ ]);
160
+ };
161
+ const encodeCreateOWRecipientTxData = (recoveryAddress, principalRecipient, rewardRecipient, amountOfPrincipalStake) => {
162
+ return owrFactoryContractInterface.encodeFunctionData('createOWRecipient', [
163
+ recoveryAddress,
164
+ principalRecipient,
165
+ rewardRecipient,
166
+ parseEther(amountOfPrincipalStake.toString()),
167
+ ]);
168
+ };
@@ -1,3 +1,12 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { DefinitionFlow } from './constants';
2
11
  export const hexWithout0x = (hex) => {
3
12
  return hex.slice(2, hex.length);
@@ -38,3 +47,13 @@ export const definitionFlow = (clusterDefinition) => {
38
47
  }
39
48
  return null;
40
49
  };
50
+ export const findDeployedBytecode = (contractAddress, provider) => __awaiter(void 0, void 0, void 0, function* () {
51
+ return yield (provider === null || provider === void 0 ? void 0 : provider.getCode(contractAddress));
52
+ });
53
+ export const isContractAvailable = (contractAddress, provider, bytecode) => __awaiter(void 0, void 0, void 0, function* () {
54
+ const code = yield findDeployedBytecode(contractAddress, provider);
55
+ if (bytecode) {
56
+ return !!code && code === bytecode;
57
+ }
58
+ return !!code && code !== '0x' && code !== '0x0';
59
+ });
@@ -176,7 +176,7 @@ export const clusterConfigV1X8 = {
176
176
  { address: '0xC35CfCd67b9C27345a54EDEcC1033F2284148c81' },
177
177
  { address: '0x33807D6F1DCe44b9C599fFE03640762A6F08C496' },
178
178
  { address: '0xc6e76F72Ea672FAe05C357157CfC37720F0aF26f' },
179
- { address: '0x86B8145c98e5BD25BA722645b15eD65f024a87EC' },
179
+ { address: '0xf6fF1a7A14D01e86a175bA958d3B6C75f2213966' },
180
180
  ],
181
181
  validators: [
182
182
  {
@@ -7,7 +7,7 @@ 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 { ethers } from 'ethers';
10
+ import { ethers, JsonRpcProvider } from 'ethers';
11
11
  import { Client, validateClusterLock } from '../src/index';
12
12
  import { clusterConfigV1X7, clusterConfigV1X8, clusterLockV1X6, clusterLockV1X7, clusterLockV1X8, nullDepositAmountsClusterLockV1X8, } from './fixtures.js';
13
13
  import { SDK_VERSION } from '../src/constants';
@@ -16,22 +16,18 @@ import { validatePayload } from '../src/ajv';
16
16
  import { HttpResponse, http } from 'msw';
17
17
  import { setupServer } from 'msw/node';
18
18
  import { hashTermsAndConditions } from '../src/verification/termsAndConditions';
19
+ import * as utils from '../src/utils';
20
+ import * as splitsHelpers from '../src/splitHelpers';
19
21
  /* eslint no-new: 0 */
20
22
  describe('Cluster Client', () => {
21
23
  var _a, _b;
22
24
  const mockConfigHash = '0x1f6c94e6c070393a68c1aa6073a21cb1fd57f0e14d2a475a2958990ab728c2fd';
23
25
  const mnemonic = (_b = (_a = ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
24
26
  const privateKey = ethers.Wallet.fromPhrase(mnemonic).privateKey;
25
- const wallet = new ethers.Wallet(privateKey);
26
- const mockSigner = wallet.connect(null);
27
- const clientInstance = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 5 }, mockSigner);
28
- // test('throws invalid ChainId when it is equal to 1', async () => {
29
- // try {
30
- // new Client({ chainId: 1 }, mockSigner)
31
- // } catch (error: any) {
32
- // expect(error.message).toBe('Obol-SDK is in Beta phase, mainnet is not yet supported')
33
- // }
34
- // })
27
+ const provider = new JsonRpcProvider('https://ethereum-holesky.publicnode.com');
28
+ const wallet = new ethers.Wallet(privateKey, provider);
29
+ const mockSigner = wallet.connect(provider);
30
+ const clientInstance = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
35
31
  test('createTermsAndConditions should return "successful authorization"', () => __awaiter(void 0, void 0, void 0, function* () {
36
32
  clientInstance['request'] = jest
37
33
  .fn()
@@ -138,7 +134,7 @@ describe('Cluster Client', () => {
138
134
  describe('Cluster Client without a signer', () => {
139
135
  const clientInstance = new Client({
140
136
  baseUrl: 'https://obol-api-dev.gcp.obol.tech',
141
- chainId: 5,
137
+ chainId: 17000,
142
138
  });
143
139
  test('createClusterDefinition should throw an error without signer', () => __awaiter(void 0, void 0, void 0, function* () {
144
140
  try {
@@ -198,3 +194,188 @@ describe('Cluster Client without a signer', () => {
198
194
  expect(termsAndConditionsHash).toEqual('0xd33721644e8f3afab1495a74abe3523cec12d48b8da6cb760972492ca3f1a273');
199
195
  }));
200
196
  });
197
+ describe('createObolRewardsSplit', () => {
198
+ var _a, _b;
199
+ jest
200
+ .spyOn(utils, 'isContractAvailable')
201
+ .mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
202
+ jest
203
+ .spyOn(splitsHelpers, 'predictSplitterAddress')
204
+ .mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xPredictedAddress'); }));
205
+ jest.spyOn(splitsHelpers, 'handleDeployOWRAndSplitter').mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () {
206
+ return yield Promise.resolve({
207
+ withdrawal_address: '0xWithdrawalAddress',
208
+ fee_recipient_address: '0xFeeRecipientAddress',
209
+ });
210
+ }));
211
+ const mnemonic = (_b = (_a = ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
212
+ const privateKey = ethers.Wallet.fromPhrase(mnemonic).privateKey;
213
+ const provider = new JsonRpcProvider('https://ethereum-holesky.publicnode.com');
214
+ const wallet = new ethers.Wallet(privateKey, provider);
215
+ const mockSigner = wallet.connect(provider);
216
+ const clientInstance = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
217
+ const clientInstanceWithourSigner = new Client({
218
+ baseUrl: 'https://obol-api-dev.gcp.obol.tech',
219
+ chainId: 17000,
220
+ });
221
+ const mockSplitRecipients = [
222
+ {
223
+ account: '0x86B8145c98e5BD25BA722645b15eD65f024a87EC',
224
+ percentAllocation: 99,
225
+ },
226
+ ];
227
+ const mockPrincipalRecipient = '0x86B8145c98e5BD25BA722645b15eD65f024a87EC';
228
+ const mockEtherAmount = 64;
229
+ it('should throw an error if signer is not defined', () => __awaiter(void 0, void 0, void 0, function* () {
230
+ yield expect(clientInstanceWithourSigner.createObolRewardsSplit({
231
+ splitRecipients: mockSplitRecipients,
232
+ principalRecipient: mockPrincipalRecipient,
233
+ etherAmount: mockEtherAmount,
234
+ })).rejects.toThrow('Signer is required in createObolRewardsSplit');
235
+ }));
236
+ it('should throw an error if chainId is not supported', () => __awaiter(void 0, void 0, void 0, function* () {
237
+ const unsupportedSplitterChainClient = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 100 }, mockSigner);
238
+ try {
239
+ yield unsupportedSplitterChainClient.createObolRewardsSplit({
240
+ splitRecipients: mockSplitRecipients,
241
+ principalRecipient: mockPrincipalRecipient,
242
+ etherAmount: mockEtherAmount,
243
+ });
244
+ }
245
+ catch (error) {
246
+ expect(error.message).toEqual('Splitter configuration is not supported on 100 chain');
247
+ }
248
+ }));
249
+ test('should throw an error on invalid recipients', () => __awaiter(void 0, void 0, void 0, function* () {
250
+ try {
251
+ yield clientInstance.createObolRewardsSplit({
252
+ splitRecipients: [
253
+ {
254
+ account: '0x86B8145c98e5BD25BA722645b15eD65f024a87EC',
255
+ percentAllocation: 22,
256
+ },
257
+ ],
258
+ principalRecipient: mockPrincipalRecipient,
259
+ etherAmount: mockEtherAmount,
260
+ });
261
+ }
262
+ catch (error) {
263
+ expect(error.message).toEqual('Schema compilation errors\', must pass "validateSplitRecipients" keyword validation');
264
+ }
265
+ }));
266
+ test('should throw an error if ObolRAFSplit is less than 1', () => __awaiter(void 0, void 0, void 0, function* () {
267
+ try {
268
+ yield clientInstance.createObolRewardsSplit({
269
+ splitRecipients: mockSplitRecipients,
270
+ principalRecipient: mockPrincipalRecipient,
271
+ etherAmount: mockEtherAmount,
272
+ ObolRAFSplit: 0.5,
273
+ });
274
+ }
275
+ catch (error) {
276
+ expect(error.message).toEqual("Schema compilation errors', must be >= 1");
277
+ }
278
+ }));
279
+ it('should return the correct withdrawal and fee recipient addresses', () => __awaiter(void 0, void 0, void 0, function* () {
280
+ const result = yield clientInstance.createObolRewardsSplit({
281
+ splitRecipients: mockSplitRecipients,
282
+ principalRecipient: mockPrincipalRecipient,
283
+ etherAmount: mockEtherAmount,
284
+ });
285
+ expect(result).toEqual({
286
+ withdrawal_address: '0xWithdrawalAddress',
287
+ fee_recipient_address: '0xFeeRecipientAddress',
288
+ });
289
+ }));
290
+ });
291
+ describe('createObolTotalSplit', () => {
292
+ var _a, _b;
293
+ jest
294
+ .spyOn(utils, 'isContractAvailable')
295
+ .mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve(true); }));
296
+ jest
297
+ .spyOn(splitsHelpers, 'predictSplitterAddress')
298
+ .mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xPredictedAddress'); }));
299
+ jest
300
+ .spyOn(splitsHelpers, 'deploySplitterContract')
301
+ .mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return yield Promise.resolve('0xSplitterAddress'); }));
302
+ const mnemonic = (_b = (_a = ethers.Wallet.createRandom().mnemonic) === null || _a === void 0 ? void 0 : _a.phrase) !== null && _b !== void 0 ? _b : '';
303
+ const privateKey = ethers.Wallet.fromPhrase(mnemonic).privateKey;
304
+ const provider = new JsonRpcProvider('https://ethereum-holesky.publicnode.com');
305
+ const wallet = new ethers.Wallet(privateKey, provider);
306
+ const mockSigner = wallet.connect(provider);
307
+ const clientInstance = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 17000 }, mockSigner);
308
+ const clientInstanceWithourSigner = new Client({
309
+ baseUrl: 'https://obol-api-dev.gcp.obol.tech',
310
+ chainId: 17000,
311
+ });
312
+ const mockSplitRecipients = [
313
+ {
314
+ account: '0x86B8145c98e5BD25BA722645b15eD65f024a87EC',
315
+ percentAllocation: 99.9,
316
+ },
317
+ ];
318
+ it('should throw an error if signer is not defined', () => __awaiter(void 0, void 0, void 0, function* () {
319
+ yield expect(clientInstanceWithourSigner.createObolTotalSplit({
320
+ splitRecipients: mockSplitRecipients,
321
+ })).rejects.toThrow('Signer is required in createObolTotalSplit');
322
+ }));
323
+ it('should throw an error if chainId is not supported', () => __awaiter(void 0, void 0, void 0, function* () {
324
+ const unsupportedSplitterChainClient = new Client({ baseUrl: 'https://obol-api-dev.gcp.obol.tech', chainId: 100 }, mockSigner);
325
+ try {
326
+ yield unsupportedSplitterChainClient.createObolTotalSplit({
327
+ splitRecipients: mockSplitRecipients,
328
+ });
329
+ }
330
+ catch (error) {
331
+ expect(error.message).toEqual('Splitter configuration is not supported on 100 chain');
332
+ }
333
+ }));
334
+ test('should throw an error on invalid recipients', () => __awaiter(void 0, void 0, void 0, function* () {
335
+ try {
336
+ yield clientInstance.createObolTotalSplit({
337
+ splitRecipients: [
338
+ {
339
+ account: '0x86B8145c98e5BD25BA722645b15eD65f024a87EC',
340
+ percentAllocation: 22,
341
+ },
342
+ ],
343
+ });
344
+ }
345
+ catch (error) {
346
+ expect(error.message).toEqual('Schema compilation errors\', must pass "validateSplitRecipients" keyword validation');
347
+ }
348
+ }));
349
+ test('should throw an error if ObolRAFSplit is less than 0.1', () => __awaiter(void 0, void 0, void 0, function* () {
350
+ try {
351
+ yield clientInstance.createObolTotalSplit({
352
+ splitRecipients: mockSplitRecipients,
353
+ ObolRAFSplit: 0.05,
354
+ });
355
+ }
356
+ catch (error) {
357
+ expect(error.message).toEqual("Schema compilation errors', must be >= 0.1");
358
+ }
359
+ }));
360
+ it('should return the correct withdrawal and fee recipient addresses and ObolRAFSplit', () => __awaiter(void 0, void 0, void 0, function* () {
361
+ const result = yield clientInstance.createObolTotalSplit({
362
+ splitRecipients: mockSplitRecipients,
363
+ ObolRAFSplit: 0.5,
364
+ });
365
+ // 0xPredictedAddress and not 0xSplitterAddress since were mocking isContractAvailable response to be true
366
+ expect(result).toEqual({
367
+ withdrawal_address: '0xPredictedAddress',
368
+ fee_recipient_address: '0xPredictedAddress',
369
+ });
370
+ }));
371
+ it('should return the correct withdrawal and fee recipient addresses without passing ObolRAFSplit', () => __awaiter(void 0, void 0, void 0, function* () {
372
+ const result = yield clientInstance.createObolTotalSplit({
373
+ splitRecipients: mockSplitRecipients,
374
+ });
375
+ // 0xPredictedAddress and not 0xSplitterAddress since were mocking isContractAvailable response to be true
376
+ expect(result).toEqual({
377
+ withdrawal_address: '0xPredictedAddress',
378
+ fee_recipient_address: '0xPredictedAddress',
379
+ });
380
+ }));
381
+ });
@@ -0,0 +1,35 @@
1
+ export declare const MultiCallContract: {
2
+ abi: ({
3
+ constant: boolean;
4
+ inputs: {
5
+ components: {
6
+ name: string;
7
+ type: string;
8
+ }[];
9
+ name: string;
10
+ type: string;
11
+ }[];
12
+ name: string;
13
+ outputs: {
14
+ name: string;
15
+ type: string;
16
+ }[];
17
+ payable: boolean;
18
+ stateMutability: string;
19
+ type: string;
20
+ } | {
21
+ constant: boolean;
22
+ inputs: {
23
+ name: string;
24
+ type: string;
25
+ }[];
26
+ name: string;
27
+ outputs: {
28
+ name: string;
29
+ type: string;
30
+ }[];
31
+ payable: boolean;
32
+ stateMutability: string;
33
+ type: string;
34
+ })[];
35
+ };
@@ -0,0 +1,52 @@
1
+ export declare const OWRFactoryContract: {
2
+ abi: ({
3
+ inputs: {
4
+ internalType: string;
5
+ name: string;
6
+ type: string;
7
+ }[];
8
+ stateMutability: string;
9
+ type: string;
10
+ name?: undefined;
11
+ anonymous?: undefined;
12
+ outputs?: undefined;
13
+ } | {
14
+ inputs: {
15
+ internalType: string;
16
+ name: string;
17
+ type: string;
18
+ }[];
19
+ name: string;
20
+ type: string;
21
+ stateMutability?: undefined;
22
+ anonymous?: undefined;
23
+ outputs?: undefined;
24
+ } | {
25
+ anonymous: boolean;
26
+ inputs: {
27
+ indexed: boolean;
28
+ internalType: string;
29
+ name: string;
30
+ type: string;
31
+ }[];
32
+ name: string;
33
+ type: string;
34
+ stateMutability?: undefined;
35
+ outputs?: undefined;
36
+ } | {
37
+ inputs: {
38
+ internalType: string;
39
+ name: string;
40
+ type: string;
41
+ }[];
42
+ name: string;
43
+ outputs: {
44
+ internalType: string;
45
+ name: string;
46
+ type: string;
47
+ }[];
48
+ stateMutability: string;
49
+ type: string;
50
+ anonymous?: undefined;
51
+ })[];
52
+ };