https://github.com/obolnetwork/obol-sdk
A typescript package for interacting with the Obol Network
https://github.com/obolnetwork/obol-sdk
Last synced: about 1 month ago
JSON representation
A typescript package for interacting with the Obol Network
- Host: GitHub
- URL: https://github.com/obolnetwork/obol-sdk
- Owner: ObolNetwork
- License: mit
- Created: 2023-03-16T15:05:15.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2026-05-04T12:22:25.000Z (about 1 month ago)
- Last Synced: 2026-05-04T12:30:02.258Z (about 1 month ago)
- Language: TypeScript
- Size: 6.74 MB
- Stars: 0
- Watchers: 2
- Forks: 2
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README

Obol SDK
This repo contains the Obol Software Development Kit, for creating Distributed Validators with the help of the [Obol API](https://docs.obol.org/api).
## Quick Start
```typescript
import { Client } from "@obolnetwork/obol-sdk";
import { Wallet } from "ethers";
// 1. Create a client (Hoodi testnet)
const signer = new Wallet(process.env.PRIVATE_KEY!);
const client = new Client({ chainId: 560048 }, signer);
// 2. Accept terms and conditions (required once per address)
await client.acceptObolLatestTermsAndConditions();
// 3. Create a cluster definition
const configHash = await client.createClusterDefinition({
name: "my-cluster",
operators: [{ address: "0xOperator1..." }, { address: "0xOperator2..." }],
validators: [{
fee_recipient_address: "0xFeeRecipient...",
withdrawal_address: "0xWithdrawal...",
}],
});
// 4. Retrieve the definition / lock (read-only, no signer needed)
const definition = await client.getClusterDefinition(configHash);
const lock = await client.getClusterLock(configHash);
```
## Getting Started
Checkout our [docs](https://docs.obol.org/docs/advanced/quickstart-sdk), [examples](https://github.com/ObolNetwork/obol-sdk-examples/), and SDK [reference](https://docs.obol.org/sdk). Further guides and walkthroughs coming soon.
## Terms and Conditions
To use obol-sdk and in order to be able to create a cluster definition or accept an invite to join a cluster, you must accept the [latest Obol terms and conditions](https://obol.org/terms.pdf) by calling acceptObolLatestTermsAndConditions.
## ⚠️ Important Security Notice:
If you're integrating this SDK with a **backend** (e.g., in Node.js), and you store a private key for executing splitter transactions, handle it with extreme caution. Ensure that:
- The private key is securely stored (e.g., in an `.env` file).
- Never commit or push your `.env` file containing the private key to version control.
## ⚡️ Integration with Safe Wallet
When integrating the Obol SDK with a **Safe Wallet**, you can either pass an RPC URL OR provide the `RPC_MAINNET` or `RPC_GNOSIS` or `RPC_SEPOLIA` or `RPC_HOODI` environment variable, pointing to the correct network's RPC URL. This is required to interact with Safe kit.
## Contributing
Please review the following guidelines:
- [How to Report Bugs](#how-to-report-bugs)
- [How to Propose Changes](#how-to-propose-changes)
- [Code Review Process](#code-review-process)
### How to Report Bugs
If you encounter a bug or unexpected behavior, please follow these steps to report it:
1. Go to the "Issues" tab of this repository.
2. Click on the "Get started" button in the Bug report section.
3. Provide a clear title and description of the issue following the format provided.
### How to Propose Changes
If you'd like to propose improvements or new features, please follow these steps:
1. Fork this repository.
2. Create a new branch for your changes.
3. Make your changes and commit them with clear messages.
4. Open a pull request with a detailed description of the changes.
### Code Review Process
All contributions are reviewed before they are merged into the main branch. Please address any feedback provided during the review process.
Thank you for contributing to Obol-SDK!
## For AI Agents and Code Generators
If you are an LLM, code-generation agent, or tool using this SDK programmatically, follow these guidelines to avoid common mistakes:
- **Primary entrypoint:** `Client` from `@obolnetwork/obol-sdk`.
- **Constructor:** `new Client({ chainId }, signer?, provider?)` – `chainId` defaults to `560048` (Hoodi).
- **All operations are namespaced** under the client instance. Do **not** construct HTTP requests manually.
### Client API Surface
| Namespace | Method | Description |
|-----------|--------|-------------|
| *(root)* | `acceptObolLatestTermsAndConditions()` | Accept T&C (required once before writes) |
| *(root)* | `createClusterDefinition(payload)` | Create a new cluster → returns `config_hash` |
| *(root)* | `acceptClusterDefinition(operatorPayload, configHash)` | Join a cluster as an operator |
| *(root)* | `getClusterDefinition(configHash)` | Fetch cluster definition (read-only) |
| *(root)* | `getClusterLock(configHash)` | Fetch cluster lock by config hash (read-only) |
| *(root)* | `getClusterLockByHash(lockHash)` | Fetch cluster lock by lock hash (read-only) |
| *(root)* | `createObolRewardsSplit(payload)` | Deploy OWR + splitter (rewards-only split) |
| *(root)* | `createObolTotalSplit(payload)` | Deploy splitter (total split) |
| *(root)* | `getOWRTranches(owrAddress)` | Read OWR tranche info (read-only on-chain) |
| `client.splits` | `createValidatorManagerAndRewardsSplit(payload)` | Deploy OVM + SplitV2 (rewards-only) |
| `client.splits` | `createValidatorManagerAndTotalSplit(payload)` | Deploy OVM + SplitV2 (total) |
| `client.splits` | `requestWithdrawal(payload)` | Request withdrawal from OVM |
| `client.splits` | `deposit(payload)` | Deposit to OVM contract |
| `client.incentives` | `getIncentivesByAddress(address)` | Fetch claimable incentives (read-only) |
| `client.incentives` | `isClaimed(contractAddress, index)` | Check if incentives claimed (read-only) |
| `client.incentives` | `claimIncentives(address)` | Claim incentives on-chain |
| `client.eoa` | `requestWithdrawal(payload)` | Request EOA withdrawal |
| `client.eoa` | `deposit(payload)` | Batch deposit validators |
| `client.exit` | `verifyPartialExitSignature(...)` | Verify BLS partial exit signature |
| `client.exit` | `verifyExitPayloadSignature(...)` | Verify ECDSA exit payload signature |
| `client.exit` | `validateExitBlobs(...)` | Validate exit blobs against cluster config |
| `client.exit` | `recombineExitBlobs(...)` | Aggregate partial exit signatures |
### Standalone Utilities
| Export | Description |
|--------|-------------|
| `validateClusterLock(lock, safeRpcUrl?)` | Cryptographic verification (signatures, hashes). Does not mirror every Charon runtime check—passing here is necessary, not sufficient, for Charon. |
### Key Rules
1. All request/response types are exported from the package root.
2. Error types exported: `ConflictError`, `SignerRequiredError`, `UnsupportedChainError`.
3. Methods that **write** (create, deploy, claim) require a `signer`. Methods that **read** (get, fetch) do not.
4. Supported chain IDs: `1` (Mainnet), `560048` (Hoodi).
5. Splitter/OVM deployment is only supported on chains 1 and 560048.
## Next.js / SSR Configuration
If using this SDK in **Next.js** or other SSR frameworks, add this minimal config to your `next.config.js`:
```javascript
webpack: (config, { isServer, webpack }) => {
if (!isServer) {
config.plugins.push(
new webpack.DefinePlugin({
'process.stdout.isTTY': 'false',
'process.stderr.isTTY': 'false',
})
);
} else {
// Server: Externalize native dependencies
config.externals = config.externals || [];
config.externals.push({
'@chainsafe/bls': 'commonjs @chainsafe/bls',
'bcrypto': 'commonjs bcrypto',
});
}
// Ignore .node files
config.plugins.push(
new webpack.IgnorePlugin({ resourceRegExp: /\.node$/ })
);
return config;
}
```