@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.
- package/dist/cjs/package.json +2 -4
- package/dist/cjs/src/abi/splitV2FactoryAbi.js +420 -0
- package/dist/cjs/src/ajv.js +24 -0
- package/dist/cjs/src/bytecodes.js +3 -1
- package/dist/cjs/src/constants.js +24 -16
- package/dist/cjs/src/index.js +10 -10
- package/dist/cjs/src/schema.js +29 -3
- package/dist/cjs/src/splits/splitHelpers.js +100 -109
- package/dist/cjs/src/splits/splits.js +77 -16
- package/dist/cjs/test/client/ajv.spec.js +32 -0
- package/dist/cjs/test/splits/splits.spec.js +76 -2
- package/dist/esm/package.json +2 -4
- package/dist/esm/src/abi/splitV2FactoryAbi.js +417 -0
- package/dist/esm/src/ajv.js +24 -0
- package/dist/esm/src/bytecodes.js +2 -0
- package/dist/esm/src/constants.js +25 -17
- package/dist/esm/src/index.js +10 -10
- package/dist/esm/src/schema.js +28 -2
- package/dist/esm/src/splits/splitHelpers.js +101 -110
- package/dist/esm/src/splits/splits.js +79 -18
- package/dist/esm/test/client/ajv.spec.js +33 -1
- package/dist/esm/test/splits/splits.spec.js +77 -3
- package/dist/types/src/abi/splitV2FactoryAbi.d.ts +60 -0
- package/dist/types/src/bytecodes.d.ts +2 -0
- package/dist/types/src/exits/verificationHelpers.d.ts +1 -0
- package/dist/types/src/schema.d.ts +30 -3
- package/dist/types/src/splits/splitHelpers.d.ts +17 -3
- package/dist/types/src/splits/splits.d.ts +28 -1
- package/dist/types/src/types.d.ts +21 -6
- package/dist/types/src/verification/common.d.ts +1 -0
- package/package.json +2 -4
- package/src/abi/splitV2FactoryAbi.ts +417 -0
- package/src/ajv.ts +33 -0
- package/src/bytecodes.ts +4 -0
- package/src/constants.ts +26 -16
- package/src/index.ts +14 -14
- package/src/schema.ts +29 -2
- package/src/splits/splitHelpers.ts +169 -124
- package/src/splits/splits.ts +115 -17
- package/src/types.ts +24 -6
|
@@ -9,20 +9,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
12
|
+
exports.requestWithdrawalFromOVM = exports.deployOVMAndSplitV2 = exports.deployOVMContract = exports.isSplitV2Deployed = exports.predictSplitV2Address = exports.formatRecipientsForSplitV2 = exports.multicall = exports.getOWRTranches = exports.deploySplitterAndOWRContracts = exports.deploySplitterContract = exports.handleDeployOWRAndSplitter = exports.predictSplitterAddress = exports.formatSplitRecipients = void 0;
|
|
13
13
|
const ethers_1 = require("ethers");
|
|
14
14
|
const OWR_1 = require("../abi/OWR");
|
|
15
15
|
const OVMFactory_1 = require("../abi/OVMFactory");
|
|
16
16
|
const SplitMain_1 = require("../abi/SplitMain");
|
|
17
17
|
const Multicall_1 = require("../abi/Multicall");
|
|
18
18
|
const constants_1 = require("../constants");
|
|
19
|
-
const
|
|
20
|
-
const viem_1 = require("viem");
|
|
21
|
-
const chains_1 = require("viem/chains");
|
|
22
|
-
const accounts_1 = require("viem/accounts");
|
|
19
|
+
const splitV2FactoryAbi_1 = require("../abi/splitV2FactoryAbi");
|
|
23
20
|
const splitMainContractInterface = new ethers_1.Interface(SplitMain_1.splitMainEthereumAbi);
|
|
24
21
|
const owrFactoryContractInterface = new ethers_1.Interface(OWR_1.OWRFactoryContract.abi);
|
|
25
22
|
const ovmFactoryContractInterface = new ethers_1.Interface(OVMFactory_1.OVMFactoryContract.abi);
|
|
23
|
+
const splitV2FactoryInterface = new ethers_1.Interface(splitV2FactoryAbi_1.splitV2FactoryAbi);
|
|
26
24
|
// Helper function to extract common recipient formatting logic
|
|
27
25
|
const formatRecipientsCommon = (recipients) => {
|
|
28
26
|
const copiedRecipients = [...recipients];
|
|
@@ -50,7 +48,7 @@ exports.formatSplitRecipients = formatSplitRecipients;
|
|
|
50
48
|
const predictSplitterAddress = ({ signer, accounts, percentAllocations, chainId, distributorFee, controllerAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
49
|
var _a, _b, _c;
|
|
52
50
|
try {
|
|
53
|
-
const splitMainContractInstance = new ethers_1.Contract(getChainConfig(chainId).
|
|
51
|
+
const splitMainContractInstance = new ethers_1.Contract(getChainConfig(chainId).SPLITMAIN_CONTRACT.address, SplitMain_1.splitMainEthereumAbi, signer);
|
|
54
52
|
let predictedSplitterAddress;
|
|
55
53
|
if (controllerAddress === ethers_1.ZeroAddress) {
|
|
56
54
|
try {
|
|
@@ -153,7 +151,7 @@ exports.handleDeployOWRAndSplitter = handleDeployOWRAndSplitter;
|
|
|
153
151
|
const createOWRContract = ({ owrArgs, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
154
152
|
var _g, _h, _j, _k, _l;
|
|
155
153
|
try {
|
|
156
|
-
const OWRFactoryInstance = new ethers_1.Contract(getChainConfig(chainId).
|
|
154
|
+
const OWRFactoryInstance = new ethers_1.Contract(getChainConfig(chainId).OWR_FACTORY_CONTRACT.address, OWR_1.OWRFactoryContract.abi, signer);
|
|
157
155
|
let tx;
|
|
158
156
|
try {
|
|
159
157
|
tx = yield OWRFactoryInstance.createOWRecipient(owrArgs.recoveryAddress, owrArgs.principalRecipient, owrArgs.predictedSplitterAddress, (0, ethers_1.parseEther)(owrArgs.amountOfPrincipalStake.toString()));
|
|
@@ -197,7 +195,7 @@ const createOWRContract = ({ owrArgs, signer, chainId, }) => __awaiter(void 0, v
|
|
|
197
195
|
const deploySplitterContract = ({ signer, accounts, percentAllocations, chainId, distributorFee, controllerAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
198
196
|
var _m, _o, _p, _q, _r;
|
|
199
197
|
try {
|
|
200
|
-
const splitMainContractInstance = new ethers_1.Contract(getChainConfig(chainId).
|
|
198
|
+
const splitMainContractInstance = new ethers_1.Contract(getChainConfig(chainId).SPLITMAIN_CONTRACT.address, SplitMain_1.splitMainEthereumAbi, signer);
|
|
201
199
|
let tx;
|
|
202
200
|
try {
|
|
203
201
|
tx = yield splitMainContractInstance.createSplit(accounts, percentAllocations, distributorFee, controllerAddress);
|
|
@@ -245,14 +243,13 @@ const deploySplitterAndOWRContracts = ({ owrArgs, splitterArgs, signer, chainId,
|
|
|
245
243
|
const splitTxData = encodeCreateSplitTxData(splitterArgs.accounts, splitterArgs.percentAllocations, splitterArgs.distributorFee, splitterArgs.controllerAddress);
|
|
246
244
|
const owrTxData = encodeCreateOWRecipientTxData(owrArgs.recoveryAddress, owrArgs.principalRecipient, owrArgs.predictedSplitterAddress, owrArgs.amountOfPrincipalStake);
|
|
247
245
|
executeCalls.push({
|
|
248
|
-
target: getChainConfig(chainId).
|
|
246
|
+
target: getChainConfig(chainId).SPLITMAIN_CONTRACT.address,
|
|
249
247
|
callData: splitTxData,
|
|
250
248
|
}, {
|
|
251
|
-
target: getChainConfig(chainId).
|
|
249
|
+
target: getChainConfig(chainId).OWR_FACTORY_CONTRACT.address,
|
|
252
250
|
callData: owrTxData,
|
|
253
251
|
});
|
|
254
|
-
const
|
|
255
|
-
const executeMultiCalls = yield (0, exports.multicall)(executeCalls, signer, multicallAddess);
|
|
252
|
+
const executeMultiCalls = yield (0, exports.multicall)(executeCalls, signer, chainId);
|
|
256
253
|
const splitAddressData = (_s = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[0]) === null || _s === void 0 ? void 0 : _s.topics[1];
|
|
257
254
|
const formattedSplitterAddress = '0x' + (splitAddressData === null || splitAddressData === void 0 ? void 0 : splitAddressData.slice(26, 66));
|
|
258
255
|
const owrAddressData = (_t = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[1]) === null || _t === void 0 ? void 0 : _t.topics[1];
|
|
@@ -294,9 +291,11 @@ const getOWRTranches = ({ owrAddress, signer, }) => __awaiter(void 0, void 0, vo
|
|
|
294
291
|
}
|
|
295
292
|
});
|
|
296
293
|
exports.getOWRTranches = getOWRTranches;
|
|
297
|
-
const multicall = (calls, signer,
|
|
294
|
+
const multicall = (calls, signer, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
298
295
|
var _w, _x, _y;
|
|
299
296
|
try {
|
|
297
|
+
const chainConfig = getChainConfig(chainId);
|
|
298
|
+
const multicallAddress = chainConfig.MULTICALL_CONTRACT.address;
|
|
300
299
|
const multiCallContractInstance = new ethers_1.Contract(multicallAddress, Multicall_1.MultiCallContract.abi, signer);
|
|
301
300
|
let tx;
|
|
302
301
|
try {
|
|
@@ -356,79 +355,46 @@ const formatRecipientsForSplitV2 = (splitRecipients) => {
|
|
|
356
355
|
}));
|
|
357
356
|
};
|
|
358
357
|
exports.formatRecipientsForSplitV2 = formatRecipientsForSplitV2;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
account: address,
|
|
372
|
-
chain,
|
|
373
|
-
transport: (0, viem_1.custom)(window.ethereum),
|
|
374
|
-
});
|
|
375
|
-
return new splits_sdk_1.SplitsClient({
|
|
376
|
-
publicClient: client,
|
|
377
|
-
walletClient: viemWalletClient,
|
|
378
|
-
chainId,
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
// For non-browser environment, extract private key from signer
|
|
383
|
-
const signerPrivateKey = signer === null || signer === void 0 ? void 0 : signer.privateKey;
|
|
384
|
-
if (!signerPrivateKey) {
|
|
385
|
-
throw new Error('Signer private key not available');
|
|
386
|
-
}
|
|
387
|
-
const privateKey = signerPrivateKey.startsWith('0x')
|
|
388
|
-
? signerPrivateKey
|
|
389
|
-
: `0x${signerPrivateKey}`;
|
|
390
|
-
const scriptAccount = (0, accounts_1.privateKeyToAccount)(privateKey);
|
|
391
|
-
const account = scriptAccount;
|
|
392
|
-
const viemWalletClient = (0, viem_1.createWalletClient)({
|
|
393
|
-
account,
|
|
394
|
-
chain,
|
|
395
|
-
transport: (0, viem_1.http)(constants_1.CHAIN_PUBLIC_RPC_URL[chainId]),
|
|
396
|
-
});
|
|
397
|
-
return new splits_sdk_1.SplitsClient({
|
|
398
|
-
publicClient: client,
|
|
399
|
-
walletClient: viemWalletClient,
|
|
400
|
-
chainId,
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
exports.createSplitsClient = createSplitsClient;
|
|
358
|
+
// Helper function to create SplitV2 parameters
|
|
359
|
+
const createSplitV2Params = (recipients, distributorFeePercent) => {
|
|
360
|
+
const addresses = recipients.map(r => r.address);
|
|
361
|
+
const allocations = recipients.map(r => Math.floor(r.percentAllocation * 1e4)); // Convert to basis points
|
|
362
|
+
const totalAllocation = allocations.reduce((sum, allocation) => sum + allocation, 0);
|
|
363
|
+
return {
|
|
364
|
+
recipients: addresses,
|
|
365
|
+
allocations,
|
|
366
|
+
totalAllocation,
|
|
367
|
+
distributionIncentive: distributorFeePercent,
|
|
368
|
+
};
|
|
369
|
+
};
|
|
405
370
|
const predictSplitV2Address = ({ splitOwnerAddress, recipients, distributorFeePercent, salt, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
406
|
-
var _z;
|
|
371
|
+
var _z, _0;
|
|
407
372
|
try {
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
return
|
|
373
|
+
const chainConfig = getChainConfig(chainId);
|
|
374
|
+
if (!((_z = chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.SPLIT_V2_FACTORY_CONTRACT) === null || _z === void 0 ? void 0 : _z.address)) {
|
|
375
|
+
throw new Error(`SplitV2 Factory not configured for chain ${chainId}`);
|
|
376
|
+
}
|
|
377
|
+
const splitV2FactoryContract = new ethers_1.Contract(chainConfig.SPLIT_V2_FACTORY_CONTRACT.address, splitV2FactoryAbi_1.splitV2FactoryAbi, signer);
|
|
378
|
+
const splitParams = createSplitV2Params(recipients, distributorFeePercent);
|
|
379
|
+
const predictedAddress = yield splitV2FactoryContract['predictDeterministicAddress((address[],uint256[],uint256,uint16),address,bytes32)'](splitParams, splitOwnerAddress, salt);
|
|
380
|
+
return predictedAddress;
|
|
416
381
|
}
|
|
417
382
|
catch (error) {
|
|
418
|
-
throw new Error(`Failed to predict SplitV2 address: ${(
|
|
383
|
+
throw new Error(`Failed to predict SplitV2 address: ${(_0 = error.message) !== null && _0 !== void 0 ? _0 : 'SplitV2 contract call failed'}`);
|
|
419
384
|
}
|
|
420
385
|
});
|
|
421
386
|
exports.predictSplitV2Address = predictSplitV2Address;
|
|
422
387
|
const isSplitV2Deployed = ({ splitOwnerAddress, recipients, distributorFeePercent, salt, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
388
|
+
var _1;
|
|
423
389
|
try {
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
return
|
|
390
|
+
const chainConfig = getChainConfig(chainId);
|
|
391
|
+
if (!((_1 = chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.SPLIT_V2_FACTORY_CONTRACT) === null || _1 === void 0 ? void 0 : _1.address)) {
|
|
392
|
+
throw new Error(`SplitV2 Factory not configured for chain ${chainId}`);
|
|
393
|
+
}
|
|
394
|
+
const splitV2FactoryContract = new ethers_1.Contract(chainConfig.SPLIT_V2_FACTORY_CONTRACT.address, splitV2FactoryAbi_1.splitV2FactoryAbi, signer);
|
|
395
|
+
const splitParams = createSplitV2Params(recipients, distributorFeePercent);
|
|
396
|
+
const [, exists] = yield splitV2FactoryContract.isDeployed(splitParams, splitOwnerAddress, salt);
|
|
397
|
+
return exists;
|
|
432
398
|
}
|
|
433
399
|
catch (error) {
|
|
434
400
|
// If the check fails, assume it's not deployed
|
|
@@ -437,17 +403,17 @@ const isSplitV2Deployed = ({ splitOwnerAddress, recipients, distributorFeePercen
|
|
|
437
403
|
});
|
|
438
404
|
exports.isSplitV2Deployed = isSplitV2Deployed;
|
|
439
405
|
const deployOVMContract = ({ OVMOwnerAddress, principalRecipient, rewardRecipient, principalThreshold, signer, chainId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
440
|
-
var
|
|
406
|
+
var _2, _3, _4;
|
|
441
407
|
try {
|
|
442
408
|
const chainConfig = getChainConfig(chainId);
|
|
443
|
-
if (!((
|
|
409
|
+
if (!((_2 = chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.OVM_FACTORY_CONTRACT) === null || _2 === void 0 ? void 0 : _2.address)) {
|
|
444
410
|
throw new Error(`OVM Factory not configured for chain ${chainId}`);
|
|
445
411
|
}
|
|
446
|
-
const ovmFactoryContract = new ethers_1.Contract(chainConfig.
|
|
412
|
+
const ovmFactoryContract = new ethers_1.Contract(chainConfig.OVM_FACTORY_CONTRACT.address, OVMFactory_1.OVMFactoryContract.abi, signer);
|
|
447
413
|
const tx = yield ovmFactoryContract.createObolValidatorManager(OVMOwnerAddress, principalRecipient, rewardRecipient, principalThreshold);
|
|
448
414
|
const receipt = yield tx.wait();
|
|
449
415
|
// Extract OVM address from logs
|
|
450
|
-
const ovmAddressLog = (
|
|
416
|
+
const ovmAddressLog = (_3 = receipt === null || receipt === void 0 ? void 0 : receipt.logs[1]) === null || _3 === void 0 ? void 0 : _3.topics[1];
|
|
451
417
|
if (!ovmAddressLog) {
|
|
452
418
|
throw new Error('Failed to extract OVM address from transaction logs');
|
|
453
419
|
}
|
|
@@ -455,60 +421,58 @@ const deployOVMContract = ({ OVMOwnerAddress, principalRecipient, rewardRecipien
|
|
|
455
421
|
return ovmAddress;
|
|
456
422
|
}
|
|
457
423
|
catch (error) {
|
|
458
|
-
throw new Error(`Failed to deploy OVM contract: ${(
|
|
424
|
+
throw new Error(`Failed to deploy OVM contract: ${(_4 = error.message) !== null && _4 !== void 0 ? _4 : 'OVM deployment failed'}`);
|
|
459
425
|
}
|
|
460
426
|
});
|
|
461
427
|
exports.deployOVMContract = deployOVMContract;
|
|
462
428
|
const deployOVMAndSplitV2 = ({ ovmArgs, rewardRecipients, isRewardsSplitterDeployed, distributorFeePercent, salt, signer, chainId, principalSplitRecipients, isPrincipalSplitDeployed, splitOwnerAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
463
|
-
var
|
|
429
|
+
var _5, _6, _7, _8, _9, _10, _11, _12, _13, _14;
|
|
464
430
|
try {
|
|
465
431
|
const chainConfig = getChainConfig(chainId);
|
|
466
|
-
if (!((
|
|
432
|
+
if (!((_5 = chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.OVM_FACTORY_CONTRACT) === null || _5 === void 0 ? void 0 : _5.address)) {
|
|
467
433
|
throw new Error(`OVM Factory not configured for chain ${chainId}`);
|
|
468
434
|
}
|
|
469
|
-
|
|
435
|
+
if (!((_6 = chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.SPLIT_V2_FACTORY_CONTRACT) === null || _6 === void 0 ? void 0 : _6.address)) {
|
|
436
|
+
throw new Error(`SplitV2 Factory not configured for chain ${chainId}`);
|
|
437
|
+
}
|
|
470
438
|
const executeCalls = [];
|
|
471
439
|
if (rewardRecipients && !isRewardsSplitterDeployed) {
|
|
472
440
|
// Create rewards split call data
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
441
|
+
const splitParams = createSplitV2Params(rewardRecipients, distributorFeePercent);
|
|
442
|
+
const rewardsSplitTxData = encodeCreateSplitV2DeterministicTxData(splitParams, splitOwnerAddress, salt);
|
|
443
|
+
executeCalls.push({
|
|
444
|
+
target: chainConfig.SPLIT_V2_FACTORY_CONTRACT.address,
|
|
445
|
+
callData: rewardsSplitTxData,
|
|
478
446
|
});
|
|
479
|
-
executeCalls.push(rewardsSplitTxData);
|
|
480
447
|
}
|
|
481
448
|
// Create principal split call data if needed (for total split scenario)
|
|
482
449
|
if (principalSplitRecipients && !isPrincipalSplitDeployed) {
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
450
|
+
const principalSplitParams = createSplitV2Params(principalSplitRecipients, distributorFeePercent);
|
|
451
|
+
const principalSplitTxData = encodeCreateSplitV2DeterministicTxData(principalSplitParams, splitOwnerAddress, salt);
|
|
452
|
+
executeCalls.push({
|
|
453
|
+
target: chainConfig.SPLIT_V2_FACTORY_CONTRACT.address,
|
|
454
|
+
callData: principalSplitTxData,
|
|
488
455
|
});
|
|
489
|
-
executeCalls.push(principalSplitTxData);
|
|
490
456
|
}
|
|
491
457
|
// Create OVM call data
|
|
492
458
|
const ovmTxData = encodeCreateOVMTxData(ovmArgs.OVMOwnerAddress, ovmArgs.principalRecipient, ovmArgs.rewardRecipient, ovmArgs.principalThreshold);
|
|
493
459
|
executeCalls.push({
|
|
494
|
-
|
|
495
|
-
|
|
460
|
+
target: chainConfig.OVM_FACTORY_CONTRACT.address,
|
|
461
|
+
callData: ovmTxData,
|
|
496
462
|
});
|
|
497
463
|
// Execute multicall
|
|
498
|
-
const executeMultiCalls = yield
|
|
499
|
-
calls: executeCalls,
|
|
500
|
-
});
|
|
464
|
+
const executeMultiCalls = yield (0, exports.multicall)(executeCalls, signer, chainId);
|
|
501
465
|
// Extract addresses from events
|
|
502
466
|
let ovmAddress;
|
|
503
|
-
const
|
|
504
|
-
if (
|
|
505
|
-
ovmAddress = (
|
|
467
|
+
const logsCount = ((_7 = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs) === null || _7 === void 0 ? void 0 : _7.length) || 0;
|
|
468
|
+
if (logsCount === 2) {
|
|
469
|
+
ovmAddress = '0x' + ((_9 = (_8 = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[1]) === null || _8 === void 0 ? void 0 : _8.topics[1]) === null || _9 === void 0 ? void 0 : _9.slice(26, 66));
|
|
506
470
|
}
|
|
507
|
-
else if (
|
|
508
|
-
ovmAddress = (
|
|
471
|
+
else if (logsCount === 5) {
|
|
472
|
+
ovmAddress = '0x' + ((_11 = (_10 = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[4]) === null || _10 === void 0 ? void 0 : _10.topics[1]) === null || _11 === void 0 ? void 0 : _11.slice(26, 66));
|
|
509
473
|
}
|
|
510
474
|
else {
|
|
511
|
-
ovmAddress = (
|
|
475
|
+
ovmAddress = '0x' + ((_13 = (_12 = executeMultiCalls === null || executeMultiCalls === void 0 ? void 0 : executeMultiCalls.logs[7]) === null || _12 === void 0 ? void 0 : _12.topics[1]) === null || _13 === void 0 ? void 0 : _13.slice(26, 66));
|
|
512
476
|
}
|
|
513
477
|
if (!ovmAddress) {
|
|
514
478
|
throw new Error('Failed to extract contract addresses from multicall events');
|
|
@@ -516,13 +480,17 @@ const deployOVMAndSplitV2 = ({ ovmArgs, rewardRecipients, isRewardsSplitterDeplo
|
|
|
516
480
|
return ovmAddress;
|
|
517
481
|
}
|
|
518
482
|
catch (error) {
|
|
519
|
-
throw new Error(`Failed to deploy OVM and SplitV2: ${(
|
|
483
|
+
throw new Error(`Failed to deploy OVM and SplitV2: ${(_14 = error.message) !== null && _14 !== void 0 ? _14 : 'Deployment failed'}`);
|
|
520
484
|
}
|
|
521
485
|
});
|
|
522
486
|
exports.deployOVMAndSplitV2 = deployOVMAndSplitV2;
|
|
523
487
|
const encodeCreateOVMTxData = (OVMOwnerAddress, principalRecipient, rewardRecipient, principalThreshold) => {
|
|
524
488
|
return ovmFactoryContractInterface.encodeFunctionData('createObolValidatorManager', [OVMOwnerAddress, principalRecipient, rewardRecipient, principalThreshold]);
|
|
525
489
|
};
|
|
490
|
+
const encodeCreateSplitV2DeterministicTxData = (splitParams, splitOwnerAddress, salt) => {
|
|
491
|
+
// creatorAddress can be kept as default https://docs.splits.org/sdk/splits-v2#createsplit
|
|
492
|
+
return splitV2FactoryInterface.encodeFunctionData('createSplitDeterministic', [splitParams, splitOwnerAddress, ethers_1.ZeroAddress, salt]);
|
|
493
|
+
};
|
|
526
494
|
// Helper function to safely get chain configuration
|
|
527
495
|
const getChainConfig = (chainId) => {
|
|
528
496
|
const config = constants_1.CHAIN_CONFIGURATION[chainId];
|
|
@@ -531,3 +499,26 @@ const getChainConfig = (chainId) => {
|
|
|
531
499
|
}
|
|
532
500
|
return config;
|
|
533
501
|
};
|
|
502
|
+
/**
|
|
503
|
+
* Requests withdrawal from an OVM contract
|
|
504
|
+
* @param ovmAddress - The address of the OVM contract
|
|
505
|
+
* @param pubKeys - Array of validator public keys in bytes format
|
|
506
|
+
* @param amounts - Array of withdrawal amounts in wei (uint64)
|
|
507
|
+
* @param signer - The signer to use for the transaction
|
|
508
|
+
* @returns Promise that resolves to the transaction hash
|
|
509
|
+
*/
|
|
510
|
+
const requestWithdrawalFromOVM = ({ ovmAddress, pubKeys, amounts, signer, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
511
|
+
var _15;
|
|
512
|
+
try {
|
|
513
|
+
// Convert string amounts to bigint
|
|
514
|
+
const bigintAmounts = amounts.map(amount => BigInt(amount));
|
|
515
|
+
const ovmContract = new ethers_1.Contract(ovmAddress, OVMFactory_1.OVMContract.abi, signer);
|
|
516
|
+
const tx = yield ovmContract.requestWithdrawal(pubKeys, bigintAmounts);
|
|
517
|
+
const receipt = yield tx.wait();
|
|
518
|
+
return { txHash: receipt.hash };
|
|
519
|
+
}
|
|
520
|
+
catch (error) {
|
|
521
|
+
throw new Error(`Failed to request withdrawal from OVM: ${(_15 = error.message) !== null && _15 !== void 0 ? _15 : 'Request withdrawal failed'}`);
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
exports.requestWithdrawalFromOVM = requestWithdrawalFromOVM;
|
|
@@ -57,22 +57,33 @@ class ObolSplits {
|
|
|
57
57
|
throw new Error(`Splitter configuration is not supported on ${this.chainId} chain`);
|
|
58
58
|
}
|
|
59
59
|
const chainConfig = constants_1.CHAIN_CONFIGURATION[this.chainId];
|
|
60
|
-
if (!(chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.
|
|
60
|
+
if (!(chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.OVM_FACTORY_CONTRACT)) {
|
|
61
61
|
throw new Error(`OVM contract factory is not configured for chain ${this.chainId}`);
|
|
62
62
|
}
|
|
63
63
|
if (!this.provider) {
|
|
64
64
|
throw new Error('Provider is required to check OVM factory contract availability');
|
|
65
65
|
}
|
|
66
|
-
const ovmFactoryConfig = chainConfig.
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
const ovmFactoryConfig = chainConfig.OVM_FACTORY_CONTRACT;
|
|
67
|
+
const splitV2FactoryConfig = chainConfig.SPLIT_V2_FACTORY_CONTRACT;
|
|
68
|
+
const multiCallConfig = chainConfig.MULTICALL_CONTRACT;
|
|
69
|
+
if (!(ovmFactoryConfig === null || ovmFactoryConfig === void 0 ? void 0 : ovmFactoryConfig.address) ||
|
|
70
|
+
!(ovmFactoryConfig === null || ovmFactoryConfig === void 0 ? void 0 : ovmFactoryConfig.bytecode) ||
|
|
71
|
+
!(splitV2FactoryConfig === null || splitV2FactoryConfig === void 0 ? void 0 : splitV2FactoryConfig.address) ||
|
|
72
|
+
!(splitV2FactoryConfig === null || splitV2FactoryConfig === void 0 ? void 0 : splitV2FactoryConfig.bytecode) ||
|
|
73
|
+
!(multiCallConfig === null || multiCallConfig === void 0 ? void 0 : multiCallConfig.address) ||
|
|
74
|
+
!(multiCallConfig === null || multiCallConfig === void 0 ? void 0 : multiCallConfig.bytecode)) {
|
|
75
|
+
throw new Error(`Contracts configuration is incomplete for chain ${this.chainId}`);
|
|
69
76
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
const checkOVMFactoryContract = yield (0, utils_1.isContractAvailable)(ovmFactoryConfig.address, this.provider, ovmFactoryConfig.bytecode);
|
|
78
|
+
const checkSplitV2FactoryContract = yield (0, utils_1.isContractAvailable)(splitV2FactoryConfig.address, this.provider, splitV2FactoryConfig.bytecode);
|
|
79
|
+
const checkMultiCallContract = yield (0, utils_1.isContractAvailable)(multiCallConfig.address, this.provider, multiCallConfig.bytecode);
|
|
80
|
+
if (!checkOVMFactoryContract ||
|
|
81
|
+
!checkSplitV2FactoryContract ||
|
|
82
|
+
!checkMultiCallContract) {
|
|
83
|
+
throw new Error(`Splitter contract is not deployed or available on chain ${this.chainId}`);
|
|
73
84
|
}
|
|
74
85
|
const retroActiveFundingRecipient = {
|
|
75
|
-
address: chainConfig.
|
|
86
|
+
address: chainConfig.RETROACTIVE_FUNDING_CONTRACT.address,
|
|
76
87
|
percentAllocation: constants_1.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT,
|
|
77
88
|
};
|
|
78
89
|
const copiedRewardsSplitRecipients = [
|
|
@@ -162,22 +173,33 @@ class ObolSplits {
|
|
|
162
173
|
throw new Error(`Splitter configuration is not supported on ${this.chainId} chain`);
|
|
163
174
|
}
|
|
164
175
|
const chainConfig = constants_1.CHAIN_CONFIGURATION[this.chainId];
|
|
165
|
-
if (!(chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.
|
|
176
|
+
if (!(chainConfig === null || chainConfig === void 0 ? void 0 : chainConfig.OVM_FACTORY_CONTRACT)) {
|
|
166
177
|
throw new Error(`OVM contract factory is not configured for chain ${this.chainId}`);
|
|
167
178
|
}
|
|
168
179
|
if (!this.provider) {
|
|
169
180
|
throw new Error('Provider is required to check OVM factory contract availability');
|
|
170
181
|
}
|
|
171
|
-
const ovmFactoryConfig = chainConfig.
|
|
172
|
-
|
|
173
|
-
|
|
182
|
+
const ovmFactoryConfig = chainConfig.OVM_FACTORY_CONTRACT;
|
|
183
|
+
const splitV2FactoryConfig = chainConfig.SPLIT_V2_FACTORY_CONTRACT;
|
|
184
|
+
const multiCallConfig = chainConfig.MULTICALL_CONTRACT;
|
|
185
|
+
if (!(ovmFactoryConfig === null || ovmFactoryConfig === void 0 ? void 0 : ovmFactoryConfig.address) ||
|
|
186
|
+
!(ovmFactoryConfig === null || ovmFactoryConfig === void 0 ? void 0 : ovmFactoryConfig.bytecode) ||
|
|
187
|
+
!(splitV2FactoryConfig === null || splitV2FactoryConfig === void 0 ? void 0 : splitV2FactoryConfig.address) ||
|
|
188
|
+
!(splitV2FactoryConfig === null || splitV2FactoryConfig === void 0 ? void 0 : splitV2FactoryConfig.bytecode) ||
|
|
189
|
+
!(multiCallConfig === null || multiCallConfig === void 0 ? void 0 : multiCallConfig.address) ||
|
|
190
|
+
!(multiCallConfig === null || multiCallConfig === void 0 ? void 0 : multiCallConfig.bytecode)) {
|
|
191
|
+
throw new Error(`Contracts configuration is incomplete for chain ${this.chainId}`);
|
|
174
192
|
}
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
193
|
+
const checkOVMFactoryContract = yield (0, utils_1.isContractAvailable)(ovmFactoryConfig.address, this.provider, ovmFactoryConfig.bytecode);
|
|
194
|
+
const checkSplitV2FactoryContract = yield (0, utils_1.isContractAvailable)(splitV2FactoryConfig.address, this.provider, splitV2FactoryConfig.bytecode);
|
|
195
|
+
const checkMultiCallContract = yield (0, utils_1.isContractAvailable)(multiCallConfig.address, this.provider, multiCallConfig.bytecode);
|
|
196
|
+
if (!checkOVMFactoryContract ||
|
|
197
|
+
!checkSplitV2FactoryContract ||
|
|
198
|
+
!checkMultiCallContract) {
|
|
199
|
+
throw new Error(`Splitter contract is not deployed or available on chain ${this.chainId}`);
|
|
178
200
|
}
|
|
179
201
|
const retroActiveFundingRecipient = {
|
|
180
|
-
address: chainConfig.
|
|
202
|
+
address: chainConfig.RETROACTIVE_FUNDING_CONTRACT.address,
|
|
181
203
|
percentAllocation: constants_1.DEFAULT_RETROACTIVE_FUNDING_REWARDS_ONLY_SPLIT,
|
|
182
204
|
};
|
|
183
205
|
const copiedRewardsSplitRecipients = [
|
|
@@ -257,5 +279,44 @@ class ObolSplits {
|
|
|
257
279
|
}
|
|
258
280
|
});
|
|
259
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Requests withdrawal from an OVM contract.
|
|
284
|
+
*
|
|
285
|
+
* This method allows requesting withdrawal of validator funds from an OVM contract.
|
|
286
|
+
* The withdrawal request includes OVM address, validator public keys and corresponding withdrawal amounts.
|
|
287
|
+
*
|
|
288
|
+
* @remarks
|
|
289
|
+
* **⚠️ Important:** If you're storing the private key in an `.env` file, ensure it is securely managed
|
|
290
|
+
* and not pushed to version control.
|
|
291
|
+
*
|
|
292
|
+
* @param {OVMRequestWithdrawalPayload} payload - Data needed to request withdrawal
|
|
293
|
+
* @returns {Promise<{txHash: string}>} Transaction hash of the withdrawal request
|
|
294
|
+
* @throws Will throw an error if the signer is not provided, OVM address is invalid, or the request fails
|
|
295
|
+
*
|
|
296
|
+
* An example of how to use requestWithdrawal:
|
|
297
|
+
* ```typescript
|
|
298
|
+
* const result = await client.splits.requestWithdrawal({
|
|
299
|
+
* ovmAddress: '0x1234567890123456789012345678901234567890',
|
|
300
|
+
* pubKeys: ['0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456'],
|
|
301
|
+
* amounts: ['32000000000'] // 32 ETH in gwei
|
|
302
|
+
* });
|
|
303
|
+
* console.log('Withdrawal requested:', result.txHash);
|
|
304
|
+
* ```
|
|
305
|
+
*/
|
|
306
|
+
requestWithdrawal(payload) {
|
|
307
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
308
|
+
if (!this.signer) {
|
|
309
|
+
throw new Error('Signer is required in requestWithdrawal');
|
|
310
|
+
}
|
|
311
|
+
// [TBD] need to move ovm verification to sdk method and use it here
|
|
312
|
+
const validatedPayload = (0, ajv_1.validatePayload)(payload, schema_1.ovmRequestWithdrawalPayloadSchema);
|
|
313
|
+
return yield (0, splitHelpers_1.requestWithdrawalFromOVM)({
|
|
314
|
+
ovmAddress: validatedPayload.ovmAddress,
|
|
315
|
+
pubKeys: validatedPayload.pubKeys,
|
|
316
|
+
amounts: validatedPayload.amounts,
|
|
317
|
+
signer: this.signer,
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
}
|
|
260
321
|
}
|
|
261
322
|
exports.ObolSplits = ObolSplits;
|
|
@@ -267,3 +267,35 @@ describe('validatePayload - OVM Schemas', () => {
|
|
|
267
267
|
});
|
|
268
268
|
});
|
|
269
269
|
});
|
|
270
|
+
describe('ovmRequestWithdrawalPayloadSchema', () => {
|
|
271
|
+
const validPayload = {
|
|
272
|
+
ovmAddress: '0x1234567890123456789012345678901234567890',
|
|
273
|
+
pubKeys: [
|
|
274
|
+
'0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
275
|
+
],
|
|
276
|
+
amounts: ['32000000000'],
|
|
277
|
+
};
|
|
278
|
+
it('should throw error when OVM address is missing', () => {
|
|
279
|
+
const payload = {
|
|
280
|
+
pubKeys: validPayload.pubKeys,
|
|
281
|
+
amounts: validPayload.amounts,
|
|
282
|
+
};
|
|
283
|
+
expect(() => (0, ajv_1.validatePayload)(payload, schema_1.ovmRequestWithdrawalPayloadSchema)).toThrow("Validation failed: must have required property 'ovmAddress'");
|
|
284
|
+
});
|
|
285
|
+
it('should throw error when OVM address is invalid', () => {
|
|
286
|
+
const payload = {
|
|
287
|
+
ovmAddress: '0x123', // Too short
|
|
288
|
+
pubKeys: validPayload.pubKeys,
|
|
289
|
+
amounts: validPayload.amounts,
|
|
290
|
+
};
|
|
291
|
+
expect(() => (0, ajv_1.validatePayload)(payload, schema_1.ovmRequestWithdrawalPayloadSchema)).toThrow('Validation failed: /ovmAddress must match pattern');
|
|
292
|
+
});
|
|
293
|
+
it('should throw error when number of public keys does not match number of amounts', () => {
|
|
294
|
+
const payload = {
|
|
295
|
+
ovmAddress: validPayload.ovmAddress,
|
|
296
|
+
pubKeys: validPayload.pubKeys,
|
|
297
|
+
amounts: ['32000000000', '16000000000'], // 2 amounts, 1 pubKey
|
|
298
|
+
};
|
|
299
|
+
expect(() => (0, ajv_1.validatePayload)(payload, schema_1.ovmRequestWithdrawalPayloadSchema)).toThrow('Validation failed: must pass "validateOVMRequestWithdrawalPayload" keyword validation');
|
|
300
|
+
});
|
|
301
|
+
});
|
|
@@ -21,6 +21,7 @@ jest.mock('../../src/splits/splitHelpers', () => ({
|
|
|
21
21
|
isSplitV2Deployed: jest.fn(),
|
|
22
22
|
deployOVMContract: jest.fn(),
|
|
23
23
|
deployOVMAndSplitV2: jest.fn(),
|
|
24
|
+
requestWithdrawalFromOVM: jest.fn(),
|
|
24
25
|
}));
|
|
25
26
|
// Mock the utils
|
|
26
27
|
jest.mock('../../src/utils', () => ({
|
|
@@ -36,6 +37,7 @@ const mockPredictSplitV2Address = splitHelpers_1.predictSplitV2Address;
|
|
|
36
37
|
const mockIsSplitV2Deployed = splitHelpers_1.isSplitV2Deployed;
|
|
37
38
|
const mockDeployOVMAndSplitV2 = splitHelpers_1.deployOVMAndSplitV2;
|
|
38
39
|
const mockDeployOVMContract = splitHelpers_1.deployOVMContract;
|
|
40
|
+
const mockRequestWithdrawalFromOVM = splitHelpers_1.requestWithdrawalFromOVM;
|
|
39
41
|
const mockIsContractAvailable = utils_1.isContractAvailable;
|
|
40
42
|
describe('ObolSplits', () => {
|
|
41
43
|
let client;
|
|
@@ -44,6 +46,8 @@ describe('ObolSplits', () => {
|
|
|
44
46
|
beforeEach(() => {
|
|
45
47
|
// Clear all mocks before each test
|
|
46
48
|
jest.clearAllMocks();
|
|
49
|
+
// Reset the mock to not be called by default
|
|
50
|
+
mockRequestWithdrawalFromOVM.mockReset();
|
|
47
51
|
mockSigner = {
|
|
48
52
|
getAddress: jest
|
|
49
53
|
.fn()
|
|
@@ -104,9 +108,9 @@ describe('ObolSplits', () => {
|
|
|
104
108
|
it('should throw error when OVM factory is not configured', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
105
109
|
// Mock chain configuration without OVM factory
|
|
106
110
|
const originalConfig = constants_1.CHAIN_CONFIGURATION[1];
|
|
107
|
-
// Create a new config object without
|
|
111
|
+
// Create a new config object without OVM_FACTORY_CONTRACT
|
|
108
112
|
const configWithoutOVM = Object.assign({}, originalConfig);
|
|
109
|
-
delete configWithoutOVM.
|
|
113
|
+
delete configWithoutOVM.OVM_FACTORY_CONTRACT;
|
|
110
114
|
constants_1.CHAIN_CONFIGURATION[1] = configWithoutOVM;
|
|
111
115
|
yield expect(client.splits.createValidatorManagerAndRewardsSplit(mockRewardsSplitPayload)).rejects.toThrow('OVM contract factory is not configured for chain 1');
|
|
112
116
|
// Restore original config
|
|
@@ -228,6 +232,76 @@ describe('ObolSplits', () => {
|
|
|
228
232
|
yield expect(clientUnsupportedChain.splits.createValidatorManagerAndTotalSplit(mockTotalSplitPayload)).rejects.toThrow('Splitter configuration is not supported on 999 chain');
|
|
229
233
|
}));
|
|
230
234
|
});
|
|
235
|
+
describe('requestWithdrawal', () => {
|
|
236
|
+
const mockOVMAddress = '0x1234567890123456789012345678901234567890';
|
|
237
|
+
const mockPubKeys = [
|
|
238
|
+
'0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
239
|
+
];
|
|
240
|
+
const mockAmounts = ['32000000000']; // 32 ETH in gwei
|
|
241
|
+
it('should request withdrawal successfully', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
242
|
+
mockRequestWithdrawalFromOVM.mockResolvedValue({
|
|
243
|
+
txHash: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
|
|
244
|
+
});
|
|
245
|
+
const result = yield client.splits.requestWithdrawal({
|
|
246
|
+
ovmAddress: mockOVMAddress,
|
|
247
|
+
pubKeys: mockPubKeys,
|
|
248
|
+
amounts: mockAmounts,
|
|
249
|
+
});
|
|
250
|
+
expect(result).toEqual({
|
|
251
|
+
txHash: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
|
|
252
|
+
});
|
|
253
|
+
expect(mockRequestWithdrawalFromOVM).toHaveBeenCalledWith({
|
|
254
|
+
ovmAddress: mockOVMAddress,
|
|
255
|
+
pubKeys: mockPubKeys,
|
|
256
|
+
amounts: mockAmounts,
|
|
257
|
+
signer: mockSigner,
|
|
258
|
+
});
|
|
259
|
+
}));
|
|
260
|
+
it('should throw error when signer is not provided', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
261
|
+
const clientWithoutSigner = new src_1.Client({ chainId: 1 }, undefined, mockProvider);
|
|
262
|
+
yield expect(clientWithoutSigner.splits.requestWithdrawal({
|
|
263
|
+
ovmAddress: mockOVMAddress,
|
|
264
|
+
pubKeys: mockPubKeys,
|
|
265
|
+
amounts: mockAmounts,
|
|
266
|
+
})).rejects.toThrow('Signer is required in requestWithdrawal');
|
|
267
|
+
}));
|
|
268
|
+
// it('should throw error when amount is below minimum (1,000,000 gwei)', async () => {
|
|
269
|
+
// await expect(
|
|
270
|
+
// client.splits.requestWithdrawal({
|
|
271
|
+
// ovmAddress: mockOVMAddress,
|
|
272
|
+
// pubKeys: mockPubKeys,
|
|
273
|
+
// amounts: ['500000'], // Below minimum of 1,000,000 gwei
|
|
274
|
+
// }),
|
|
275
|
+
// ).rejects.toThrow('Validation failed');
|
|
276
|
+
// });
|
|
277
|
+
it('should handle multiple validators withdrawal request', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
278
|
+
const multiplePubKeys = [
|
|
279
|
+
'0x123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456',
|
|
280
|
+
'0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd',
|
|
281
|
+
];
|
|
282
|
+
const multipleAmounts = [
|
|
283
|
+
'32000000000', // 32 ETH
|
|
284
|
+
'16000000000', // 16 ETH
|
|
285
|
+
];
|
|
286
|
+
mockRequestWithdrawalFromOVM.mockResolvedValue({
|
|
287
|
+
txHash: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
|
|
288
|
+
});
|
|
289
|
+
const result = yield client.splits.requestWithdrawal({
|
|
290
|
+
ovmAddress: mockOVMAddress,
|
|
291
|
+
pubKeys: multiplePubKeys,
|
|
292
|
+
amounts: multipleAmounts,
|
|
293
|
+
});
|
|
294
|
+
expect(result).toEqual({
|
|
295
|
+
txHash: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
|
|
296
|
+
});
|
|
297
|
+
expect(mockRequestWithdrawalFromOVM).toHaveBeenCalledWith({
|
|
298
|
+
ovmAddress: mockOVMAddress,
|
|
299
|
+
pubKeys: multiplePubKeys,
|
|
300
|
+
amounts: multipleAmounts,
|
|
301
|
+
signer: mockSigner,
|
|
302
|
+
});
|
|
303
|
+
}));
|
|
304
|
+
});
|
|
231
305
|
describe('constructor', () => {
|
|
232
306
|
it('should create Client instance with splits property', () => {
|
|
233
307
|
const testClient = new src_1.Client({ chainId: 1 }, mockSigner, mockProvider);
|