Skip to content

Commit 38992b9

Browse files
committed
feat: add validator unstake via Pier Two API
- Add unstake:generate, unstake:bulk, unstake:queue commands - Support pubkeys from CLI args or file - Confirmation prompts before broadcasting - Update README with all commands and env vars
1 parent 2b8df7c commit 38992b9

7 files changed

Lines changed: 684 additions & 30 deletions

File tree

.env.example

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,18 @@ HARVEST_KEEPER_ADDRESS=0x...
1313
# CubeSigner session file path (default: signer-session.json)
1414
CUBIST_SESSION_FILE=signer-session.json
1515

16-
# End block number for harvest (optional - if not set, uses current finalized block)
16+
# End block number for harvest (required)
1717
END_BLOCK=
18+
19+
# ============================================
20+
# Validator Unstake (Pier Two API)
21+
# ============================================
22+
23+
# Pier Two API Key (required for unstake operations)
24+
PIER2_API_KEY=
25+
26+
# Optional: Pier Two API Base URL (defaults to mainnet)
27+
# PIER2_BASE_URL=https://gw-1.api.piertwo.io
28+
29+
# Optional: File containing validator pubkeys (one per line)
30+
# VALIDATOR_PUBKEYS_FILE=validator-pubkeys.txt

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ node_modules/
33
dist/
44
signer-session.json
55
*.json.bak
6+
validator-pubkeys.txt
7+
exit-messages.json

README.md

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# PirexEth Ops CLI
22

3-
A CLI tool for PirexEth operations (harvest, dissolve-validator, etc.) using CubeSigner for transaction signing.
3+
A CLI tool for PirexEth protocol operations using CubeSigner and Pier Two API.
44

55
## Available Commands
66

77
- **harvest** - Harvest ETH rewards from the RewardRecipient contract
8+
- **unstake** - Exit validators via Pier Two API
89

910
## Setup
1011

@@ -18,61 +19,99 @@ A CLI tool for PirexEth operations (harvest, dissolve-validator, etc.) using Cub
1819
cp .env.example .env
1920
```
2021

21-
3. Configure your `.env` file:
22-
- `RPC_URL`: Your Ethereum RPC endpoint (Alchemy, Infura, etc.)
23-
- `NETWORK`: `mainnet` or `holesky`
24-
- `PIREX_ETH_ADDRESS`: The PirexEth contract address
25-
- `HARVEST_KEEPER_ADDRESS`: The address of the CubeSigner key used for harvesting
26-
- `CUBIST_SESSION_FILE`: Path to the CubeSigner session JSON file (default: `signer-session.json`)
22+
3. Configure your `.env` file (see sections below for specific operations)
2723

28-
4. Place your CubeSigner session file (e.g., `signer-session.json`) in the project root.
24+
4. Place your CubeSigner session file (e.g., `signer-session.json`) in the project root (for harvest operations).
2925

3026
## Usage
3127

32-
### Harvest
28+
---
29+
30+
## Harvest Command
31+
32+
Harvest ETH rewards from the RewardRecipient contract.
33+
34+
### Environment Variables (Harvest)
35+
36+
- `RPC_URL`: Your Ethereum RPC endpoint
37+
- `NETWORK`: `mainnet` or `holesky`
38+
- `PIREX_ETH_ADDRESS`: The PirexEth contract address
39+
- `HARVEST_KEEPER_ADDRESS`: The CubeSigner key address
40+
- `CUBIST_SESSION_FILE`: Path to CubeSigner session file (default: `signer-session.json`)
41+
- `END_BLOCK`: Block number for harvest (required)
42+
43+
### Harvest Commands
3344

34-
Run the harvest command (simulates first, then prompts to broadcast):
3545
```bash
46+
# Simulate first, then prompt to broadcast
3647
pnpm run harvest
37-
```
3848

39-
Or simulate only:
40-
```bash
49+
# Simulate only
4150
pnpm run harvest:simulate
42-
```
4351

44-
Or broadcast directly (skip confirmation):
45-
```bash
52+
# Broadcast directly (skip confirmation)
4653
pnpm run harvest:broadcast
4754
```
4855

49-
## Harvest Command
50-
5156
### What it does
5257

5358
1. Loads the CubeSigner session and refreshes it
5459
2. Connects to the specified network using the RPC URL
5560
3. Fetches the RewardRecipient address from PirexEth contract
56-
4. Gets the entire ETH balance of the RewardRecipient
61+
4. Gets the ETH balance of the RewardRecipient at the specified END_BLOCK
5762
5. Signs the transaction using CubeSigner
58-
6. Calls `harvest(amount, endBlock)` with:
59-
- `amount`: The entire ETH balance
60-
- `endBlock`: The current finalized block number
61-
7. Waits for transaction confirmation and reports success/failure
62-
8. **Prints the state values you need to manually update in AWS Secrets Manager**
63+
6. Calls `harvest(amount, endBlock)`
64+
7. Waits for confirmation and prints the state to update in AWS Secrets Manager
65+
66+
---
67+
68+
## Validator Unstake (Exit) Command
69+
70+
Exit validators via Pier Two API.
71+
72+
### Environment Variables (Unstake)
73+
74+
- `PIER2_API_KEY`: Your Pier Two API key (required)
75+
- `PIER2_BASE_URL`: Optional, defaults to `https://gw-1.api.piertwo.io`
76+
- `VALIDATOR_PUBKEYS_FILE`: File with pubkeys, one per line (default: `validator-pubkeys.txt`)
77+
78+
### Unstake Commands
79+
80+
```bash
81+
# Generate exit messages, then prompt to broadcast
82+
pnpm run unstake:generate
83+
84+
# Generate and broadcast in one request
85+
pnpm run unstake:bulk
86+
87+
# Show validator queue stats
88+
pnpm run unstake:queue
89+
90+
# Pass pubkeys directly
91+
pnpm run unstake:generate 0x1234... 0x5678...
92+
```
93+
94+
### Providing Validator Pubkeys
95+
96+
1. **Command line**: `pnpm run unstake:generate 0x1234... 0x5678...`
97+
2. **File**: Create `validator-pubkeys.txt` with one pubkey per line
98+
3. **Custom file**: Set `VALIDATOR_PUBKEYS_FILE` in `.env`
99+
100+
---
63101

64-
## Manual State Update
102+
## Manual State Update (After Harvest)
65103

66-
After a successful harvest, the script will print the JSON state you need to update in AWS Secrets Manager (HARVEST_KEEPER_STATE_SECRET_ID). This includes:
67-
- `lastHarvestCheckpointBlock`: The finalized block used for harvest
104+
After a successful harvest, update AWS Secrets Manager with:
105+
- `lastHarvestCheckpointBlock`: The block used for harvest
68106
- `lastRewards`: Reset to "0"
69107
- `lastBlockRewards`: Reset to "0"
70108
- `lastMevRewards`: Reset to "0"
71109

72-
It will also print the refreshed CubeSigner session if you need to update it in Secrets Manager.
110+
---
73111

74112
## Security Notes
75113

76114
- Never commit your `.env` file with real credentials
77115
- Never commit your `signer-session.json` file
116+
- Never commit `validator-pubkeys.txt` with real pubkeys
78117
- The CubeSigner key should only have permissions to call the `harvest` function

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
"build": "tsc",
88
"harvest": "npx ts-node src/index.ts simulate",
99
"harvest:simulate": "npx ts-node src/index.ts simulate",
10-
"harvest:broadcast": "npx ts-node src/index.ts broadcast"
10+
"harvest:broadcast": "npx ts-node src/index.ts broadcast",
11+
"unstake": "npx ts-node src/unstake.ts",
12+
"unstake:generate": "npx ts-node src/unstake.ts generate",
13+
"unstake:bulk": "npx ts-node src/unstake.ts bulk",
14+
"unstake:queue": "npx ts-node src/unstake.ts queue"
1115
},
1216
"dependencies": {
1317
"@cubist-labs/cubesigner-sdk": "^0.1.50",
18+
"axios": "^1.6.0",
1419
"viem": "^2.21.0",
1520
"dotenv": "^16.4.5"
1621
},

0 commit comments

Comments
 (0)