Skip to content

Commit be14139

Browse files
committed
ovm methods
1 parent 5c52b87 commit be14139

7 files changed

Lines changed: 1123 additions & 2183 deletions

File tree

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ node_modules
55
.DS_Store
66

77
# Local
8-
dist
8+
dist
9+
10+
# Environment variables
11+
.env
12+
.env.local
13+
.env.*.local

TS-Example/env.example

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# ============================================================================
2+
# REQUIRED ENVIRONMENT VARIABLES
3+
# ============================================================================
4+
5+
# Your Ethereum private key (required for signing transactions)
6+
# IMPORTANT: Never commit your actual private key to version control!
7+
# Add your private key here (with or without 0x prefix)
8+
PRIVATE_KEY=
9+
10+
# ============================================================================
11+
# OPTIONAL ENVIRONMENT VARIABLES (with defaults)
12+
# ============================================================================
13+
14+
# Network Configuration
15+
CHAIN_ID=560048
16+
BASE_URL=https://obol-api-nonprod-dev.dev.obol.tech
17+
RPC_HOODI=https://ethereum-hoodi-rpc.publicnode.com
18+
RPC_URL=https://ethereum-hoodi-rpc.publicnode.com
19+
20+
# Cluster Names
21+
CLUSTER_NAME_REWARDS_SPLIT=testOVMRewardsSplit
22+
CLUSTER_NAME_TOTAL_SPLIT=testOVMTotalSplit
23+
24+
# Cluster Configuration
25+
NUM_VALIDATORS=3
26+
NUM_OPERATORS=4

TS-Example/index.ts

Lines changed: 146 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { ethers } from "ethers";
1+
import { ethers, JsonRpcProvider } from "ethers";
22
import { Client, validateClusterLock, ClusterDefinition, ClusterLock, OperatorPayload, RewardsSplitPayload, ClusterValidator, TotalSplitPayload, ClaimIncentivesResponse, SignerType } from "@obolnetwork/obol-sdk";
3-
import { ClaimableIncentives, ExitClusterConfig, ExitValidationPayload, ProviderType } from "@obolnetwork/obol-sdk/dist/types/src/types";
3+
import type { ClaimableIncentives, ExitClusterConfig, ExitValidationPayload, ProviderType } from "@obolnetwork/obol-sdk";
44

55
//To run the example in terminal, we can create a random privatekey to instanisiate obol-sdk Client
66
const clusterConfig = {
@@ -208,6 +208,150 @@ const createObolTotalSplit = async ({
208208
}
209209
};
210210

211+
/**
212+
* Creates an OVM (One-Withdrawal-Registry) and Rewards Split using the splits class
213+
* @param rewardsSplitConfig Configuration for rewards split including recipients, OVM owner, principal recipient, and distributor fee
214+
* @returns Object containing withdrawal_address (OVM) and fee_recipient_address (Splitter)
215+
*/
216+
const createRewardsSplit = async (rewardsSplitConfig: {
217+
rewardSplitRecipients: Array<{ address: string; percentAllocation: number }>;
218+
OVMOwnerAddress: string;
219+
principalRecipient: string;
220+
distributorFeePercent: number;
221+
splitOwnerAddress?: string;
222+
}): Promise<{ withdrawal_address: string; fee_recipient_address: string }> => {
223+
try {
224+
const result = await client.splits.createValidatorManagerAndRewardsSplit({
225+
rewardSplitRecipients: rewardsSplitConfig.rewardSplitRecipients,
226+
OVMOwnerAddress: rewardsSplitConfig.OVMOwnerAddress,
227+
principalRecipient: rewardsSplitConfig.principalRecipient,
228+
distributorFeePercent: rewardsSplitConfig.distributorFeePercent,
229+
splitOwnerAddress: rewardsSplitConfig.splitOwnerAddress || rewardsSplitConfig.OVMOwnerAddress,
230+
});
231+
return {
232+
withdrawal_address: result.withdrawal_address,
233+
fee_recipient_address: result.fee_recipient_address,
234+
};
235+
} catch (err) {
236+
console.log(err, "err");
237+
throw err;
238+
}
239+
};
240+
241+
/**
242+
* Creates an OVM (One-Withdrawal-Registry) and Total Split using the splits class
243+
* @param totalSplitConfig Configuration for total split including reward and principal recipients, OVM owner, and distributor fee
244+
* @returns Object containing withdrawal_address (OVM) and fee_recipient_address (Splitter)
245+
*/
246+
const createTotalSplit = async (totalSplitConfig: {
247+
rewardSplitRecipients: Array<{ address: string; percentAllocation: number }>;
248+
principalSplitRecipients: Array<{ address: string; percentAllocation: number }>;
249+
OVMOwnerAddress: string;
250+
distributorFeePercent: number;
251+
splitOwnerAddress?: string;
252+
}): Promise<{ withdrawal_address: string; fee_recipient_address: string }> => {
253+
try {
254+
const result = await client.splits.createValidatorManagerAndTotalSplit({
255+
rewardSplitRecipients: totalSplitConfig.rewardSplitRecipients,
256+
principalSplitRecipients: totalSplitConfig.principalSplitRecipients,
257+
OVMOwnerAddress: totalSplitConfig.OVMOwnerAddress,
258+
distributorFeePercent: totalSplitConfig.distributorFeePercent,
259+
splitOwnerAddress: totalSplitConfig.splitOwnerAddress || totalSplitConfig.OVMOwnerAddress,
260+
});
261+
return {
262+
withdrawal_address: result.withdrawal_address,
263+
fee_recipient_address: result.fee_recipient_address,
264+
};
265+
} catch (err) {
266+
console.log(err, "err");
267+
throw err;
268+
}
269+
};
270+
271+
/**
272+
* Creates a cluster definition with rewards split configuration
273+
* @param clusterName Name of the cluster
274+
* @param ovmAddress OVM withdrawal address
275+
* @param splitterAddress Splitter fee recipient address
276+
* @param numValidators Number of validators in the cluster
277+
* @param numOperators Number of operators in the cluster
278+
* @returns The config hash of the created cluster definition
279+
*/
280+
const createRewardsSplitCluster = async (
281+
clusterName: string,
282+
ovmAddress: string,
283+
splitterAddress: string,
284+
numValidators: number = 3,
285+
numOperators: number = 4,
286+
): Promise<string> => {
287+
try {
288+
// Create operators array with empty addresses for solo cluster
289+
const operators = Array.from({ length: numOperators }, () => ({
290+
address: "",
291+
}));
292+
293+
// Create validators array - all validators use the same OVM and splitter addresses
294+
const validators = Array.from({ length: numValidators }, () => ({
295+
withdrawal_address: ovmAddress,
296+
fee_recipient_address: splitterAddress,
297+
}));
298+
299+
const clusterConfig = {
300+
name: clusterName,
301+
operators,
302+
validators,
303+
};
304+
305+
const configHash = await client.createClusterDefinition(clusterConfig);
306+
return configHash;
307+
} catch (err) {
308+
console.log(err, "err");
309+
throw err;
310+
}
311+
};
312+
313+
/**
314+
* Creates a cluster definition with total split configuration
315+
* @param clusterName Name of the cluster
316+
* @param ovmAddress OVM withdrawal address
317+
* @param splitterAddress Splitter fee recipient address
318+
* @param numValidators Number of validators in the cluster
319+
* @param numOperators Number of operators in the cluster
320+
* @returns The config hash of the created cluster definition
321+
*/
322+
const createTotalSplitCluster = async (
323+
clusterName: string,
324+
ovmAddress: string,
325+
splitterAddress: string,
326+
numValidators: number = 3,
327+
numOperators: number = 4,
328+
): Promise<string> => {
329+
try {
330+
// Create operators array with empty addresses for solo cluster
331+
const operators = Array.from({ length: numOperators }, () => ({
332+
address: "",
333+
}));
334+
335+
// Create validators array - all validators use the same OVM and splitter addresses
336+
const validators = Array.from({ length: numValidators }, () => ({
337+
withdrawal_address: ovmAddress,
338+
fee_recipient_address: splitterAddress,
339+
}));
340+
341+
const clusterConfig = {
342+
name: clusterName,
343+
operators,
344+
validators,
345+
};
346+
347+
const configHash = await client.createClusterDefinition(clusterConfig);
348+
return configHash;
349+
} catch (err) {
350+
console.log(err, "err");
351+
throw err;
352+
}
353+
};
354+
211355
/**
212356
* Activates cluster by depositing 32 ethers
213357
* @param clusterLock The cluster lock that contains the validator to be activated

TS-Example/package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@
22
"name": "ts-example",
33
"version": "1.0.0",
44
"description": "",
5+
"packageManager": "yarn@1.22.22",
56
"scripts": {
67
"build": "esbuild ./*.ts --outdir=dist --out-extension:.js=.mjs --format=esm",
7-
"start": "node dist/index.mjs"
8+
"start": "node dist/index.mjs",
9+
"build:test-splits": "esbuild test-splits.ts --outdir=dist --out-extension:.js=.mjs --format=esm --platform=node",
10+
"test:splits": "yarn build:test-splits && node dist/test-splits.mjs"
811
},
912
"author": "",
1013
"license": "ISC",
1114
"devDependencies": {
15+
"@types/node": "^20.0.0",
1216
"esbuild": "^0.18.17",
1317
"typescript": "^5.1.6"
1418
},
1519
"dependencies": {
16-
"@obolnetwork/obol-sdk": "^2.6.0",
20+
"@obolnetwork/obol-sdk": "^2.11.8",
21+
"dotenv": "^17.2.2",
1722
"ethers": "^6.4.0"
1823
}
1924
}

0 commit comments

Comments
 (0)