genlayer 0.34.0 → 0.34.3
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/index.js +13 -3
- package/package.json +11 -2
- package/.eslintignore +0 -2
- package/.github/workflows/cli-docs.yml +0 -121
- package/.github/workflows/publish-beta.yml +0 -41
- package/.github/workflows/publish.yml +0 -43
- package/.github/workflows/validate-code.yml +0 -47
- package/.prettierignore +0 -19
- package/.prettierrc +0 -12
- package/.release-it.json +0 -64
- package/CHANGELOG.md +0 -425
- package/CLAUDE.md +0 -55
- package/CONTRIBUTING.md +0 -117
- package/docker-compose.yml +0 -154
- package/docs/delegator-guide.md +0 -203
- package/docs/validator-guide.md +0 -329
- package/esbuild.config.dev.js +0 -17
- package/esbuild.config.js +0 -22
- package/esbuild.config.prod.js +0 -17
- package/eslint.config.js +0 -60
- package/renovate.json +0 -22
- package/src/commands/account/create.ts +0 -30
- package/src/commands/account/export.ts +0 -106
- package/src/commands/account/import.ts +0 -135
- package/src/commands/account/index.ts +0 -129
- package/src/commands/account/list.ts +0 -34
- package/src/commands/account/lock.ts +0 -39
- package/src/commands/account/remove.ts +0 -30
- package/src/commands/account/send.ts +0 -162
- package/src/commands/account/show.ts +0 -74
- package/src/commands/account/unlock.ts +0 -56
- package/src/commands/account/use.ts +0 -21
- package/src/commands/config/getSetReset.ts +0 -51
- package/src/commands/config/index.ts +0 -30
- package/src/commands/contracts/call.ts +0 -39
- package/src/commands/contracts/code.ts +0 -33
- package/src/commands/contracts/deploy.ts +0 -157
- package/src/commands/contracts/index.ts +0 -86
- package/src/commands/contracts/schema.ts +0 -31
- package/src/commands/contracts/write.ts +0 -49
- package/src/commands/general/index.ts +0 -45
- package/src/commands/general/init.ts +0 -179
- package/src/commands/general/start.ts +0 -116
- package/src/commands/general/stop.ts +0 -26
- package/src/commands/localnet/index.ts +0 -100
- package/src/commands/localnet/validators.ts +0 -269
- package/src/commands/network/index.ts +0 -29
- package/src/commands/network/setNetwork.ts +0 -77
- package/src/commands/scaffold/index.ts +0 -16
- package/src/commands/scaffold/new.ts +0 -34
- package/src/commands/staking/StakingAction.ts +0 -279
- package/src/commands/staking/delegatorClaim.ts +0 -41
- package/src/commands/staking/delegatorExit.ts +0 -56
- package/src/commands/staking/delegatorJoin.ts +0 -44
- package/src/commands/staking/index.ts +0 -357
- package/src/commands/staking/setIdentity.ts +0 -78
- package/src/commands/staking/setOperator.ts +0 -46
- package/src/commands/staking/stakingInfo.ts +0 -584
- package/src/commands/staking/validatorClaim.ts +0 -43
- package/src/commands/staking/validatorDeposit.ts +0 -48
- package/src/commands/staking/validatorExit.ts +0 -63
- package/src/commands/staking/validatorHistory.ts +0 -298
- package/src/commands/staking/validatorJoin.ts +0 -47
- package/src/commands/staking/validatorPrime.ts +0 -73
- package/src/commands/staking/wizard.ts +0 -809
- package/src/commands/transactions/appeal.ts +0 -39
- package/src/commands/transactions/index.ts +0 -39
- package/src/commands/transactions/receipt.ts +0 -90
- package/src/commands/update/index.ts +0 -25
- package/src/commands/update/ollama.ts +0 -103
- package/src/lib/actions/BaseAction.ts +0 -299
- package/src/lib/clients/jsonRpcClient.ts +0 -41
- package/src/lib/clients/system.ts +0 -73
- package/src/lib/config/ConfigFileManager.ts +0 -194
- package/src/lib/config/KeychainManager.ts +0 -89
- package/src/lib/config/simulator.ts +0 -68
- package/src/lib/config/text.ts +0 -2
- package/src/lib/errors/missingRequirement.ts +0 -9
- package/src/lib/errors/versionRequired.ts +0 -9
- package/src/lib/interfaces/ISimulatorService.ts +0 -37
- package/src/lib/services/simulator.ts +0 -351
- package/src/types/node-fetch.d.ts +0 -1
- package/tests/actions/appeal.test.ts +0 -99
- package/tests/actions/call.test.ts +0 -94
- package/tests/actions/code.test.ts +0 -87
- package/tests/actions/create.test.ts +0 -65
- package/tests/actions/deploy.test.ts +0 -420
- package/tests/actions/getSetReset.test.ts +0 -88
- package/tests/actions/init.test.ts +0 -467
- package/tests/actions/lock.test.ts +0 -86
- package/tests/actions/new.test.ts +0 -80
- package/tests/actions/ollama.test.ts +0 -193
- package/tests/actions/receipt.test.ts +0 -261
- package/tests/actions/schema.test.ts +0 -94
- package/tests/actions/setNetwork.test.ts +0 -160
- package/tests/actions/staking.test.ts +0 -279
- package/tests/actions/start.test.ts +0 -235
- package/tests/actions/stop.test.ts +0 -77
- package/tests/actions/unlock.test.ts +0 -139
- package/tests/actions/validators.test.ts +0 -750
- package/tests/actions/write.test.ts +0 -102
- package/tests/commands/account.test.ts +0 -146
- package/tests/commands/appeal.test.ts +0 -58
- package/tests/commands/call.test.ts +0 -78
- package/tests/commands/code.test.ts +0 -69
- package/tests/commands/config.test.ts +0 -54
- package/tests/commands/deploy.test.ts +0 -83
- package/tests/commands/init.test.ts +0 -101
- package/tests/commands/localnet.test.ts +0 -131
- package/tests/commands/network.test.ts +0 -60
- package/tests/commands/new.test.ts +0 -68
- package/tests/commands/receipt.test.ts +0 -142
- package/tests/commands/schema.test.ts +0 -67
- package/tests/commands/staking.test.ts +0 -329
- package/tests/commands/stop.test.ts +0 -27
- package/tests/commands/up.test.ts +0 -105
- package/tests/commands/update.test.ts +0 -45
- package/tests/commands/write.test.ts +0 -76
- package/tests/index.test.ts +0 -56
- package/tests/libs/baseAction.test.ts +0 -516
- package/tests/libs/configFileManager.test.ts +0 -117
- package/tests/libs/jsonRpcClient.test.ts +0 -59
- package/tests/libs/keychainManager.test.ts +0 -156
- package/tests/libs/system.test.ts +0 -148
- package/tests/services/simulator.test.ts +0 -705
- package/tests/utils.ts +0 -13
- package/tsconfig.json +0 -120
- package/vitest.config.ts +0 -12
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import {StakingAction, StakingConfig} from "./StakingAction";
|
|
2
|
-
import type {Address} from "genlayer-js/types";
|
|
3
|
-
import {abi} from "genlayer-js";
|
|
4
|
-
|
|
5
|
-
export interface ValidatorExitOptions extends StakingConfig {
|
|
6
|
-
validator: string;
|
|
7
|
-
shares: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class ValidatorExitAction extends StakingAction {
|
|
11
|
-
constructor() {
|
|
12
|
-
super();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async execute(options: ValidatorExitOptions): Promise<void> {
|
|
16
|
-
this.startSpinner("Initiating validator exit...");
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
let shares: bigint;
|
|
20
|
-
try {
|
|
21
|
-
shares = BigInt(options.shares);
|
|
22
|
-
if (shares <= 0n) throw new Error("must be positive");
|
|
23
|
-
} catch {
|
|
24
|
-
this.failSpinner(`Invalid shares value: "${options.shares}". Must be a positive whole number.`);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const validatorWallet = options.validator as Address;
|
|
29
|
-
const {walletClient, publicClient} = await this.getViemClients(options);
|
|
30
|
-
|
|
31
|
-
this.setSpinnerText(`Exiting validator ${validatorWallet} with ${shares} shares...`);
|
|
32
|
-
|
|
33
|
-
const hash = await walletClient.writeContract({
|
|
34
|
-
address: validatorWallet,
|
|
35
|
-
abi: abi.VALIDATOR_WALLET_ABI,
|
|
36
|
-
functionName: "validatorExit",
|
|
37
|
-
args: [shares],
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const receipt = await publicClient.waitForTransactionReceipt({hash});
|
|
41
|
-
|
|
42
|
-
// Check epoch to determine note
|
|
43
|
-
const readClient = await this.getReadOnlyStakingClient(options);
|
|
44
|
-
const epochInfo = await readClient.getEpochInfo();
|
|
45
|
-
const isEpochZero = epochInfo.currentEpoch === 0n;
|
|
46
|
-
|
|
47
|
-
const output = {
|
|
48
|
-
transactionHash: receipt.transactionHash,
|
|
49
|
-
validator: validatorWallet,
|
|
50
|
-
sharesWithdrawn: shares.toString(),
|
|
51
|
-
blockNumber: receipt.blockNumber.toString(),
|
|
52
|
-
gasUsed: receipt.gasUsed.toString(),
|
|
53
|
-
note: isEpochZero
|
|
54
|
-
? "Epoch 0: Withdrawal claimable immediately"
|
|
55
|
-
: "Withdrawal will be claimable after the unbonding period",
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
this.succeedSpinner("Exit initiated successfully!", output);
|
|
59
|
-
} catch (error: any) {
|
|
60
|
-
this.failSpinner("Failed to exit", error.message || error);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
import {StakingAction, StakingConfig, BUILT_IN_NETWORKS} from "./StakingAction";
|
|
2
|
-
import type {Address, GenLayerChain} from "genlayer-js/types";
|
|
3
|
-
import {createPublicClient, http} from "viem";
|
|
4
|
-
import Table from "cli-table3";
|
|
5
|
-
import chalk from "chalk";
|
|
6
|
-
|
|
7
|
-
// Event ABIs for log fetching
|
|
8
|
-
const SLASH_EVENT_ABI = {
|
|
9
|
-
type: "event",
|
|
10
|
-
name: "SlashedFromIdleness",
|
|
11
|
-
inputs: [
|
|
12
|
-
{name: "validator", type: "address", indexed: true},
|
|
13
|
-
{name: "txId", type: "bytes32", indexed: false},
|
|
14
|
-
{name: "epoch", type: "uint256", indexed: false},
|
|
15
|
-
{name: "percentage", type: "uint256", indexed: false},
|
|
16
|
-
],
|
|
17
|
-
} as const;
|
|
18
|
-
|
|
19
|
-
const REWARD_EVENT_ABI = {
|
|
20
|
-
type: "event",
|
|
21
|
-
name: "ValidatorPrime",
|
|
22
|
-
inputs: [
|
|
23
|
-
{name: "validator", type: "address", indexed: false},
|
|
24
|
-
{name: "epoch", type: "uint256", indexed: false},
|
|
25
|
-
{name: "validatorRewards", type: "uint256", indexed: false},
|
|
26
|
-
{name: "delegatorRewards", type: "uint256", indexed: false},
|
|
27
|
-
],
|
|
28
|
-
} as const;
|
|
29
|
-
|
|
30
|
-
export interface ValidatorHistoryOptions extends StakingConfig {
|
|
31
|
-
validator?: string;
|
|
32
|
-
fromBlock?: string;
|
|
33
|
-
fromEpoch?: string;
|
|
34
|
-
epochs?: string;
|
|
35
|
-
limit?: string;
|
|
36
|
-
all?: boolean;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
interface SlashEvent {
|
|
40
|
-
type: "slash";
|
|
41
|
-
epoch: bigint;
|
|
42
|
-
txId: string;
|
|
43
|
-
percentage: bigint;
|
|
44
|
-
blockNumber: bigint;
|
|
45
|
-
timestamp: Date;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
interface RewardEvent {
|
|
49
|
-
type: "reward";
|
|
50
|
-
epoch: bigint;
|
|
51
|
-
validatorRewards: bigint;
|
|
52
|
-
delegatorRewards: bigint;
|
|
53
|
-
blockNumber: bigint;
|
|
54
|
-
timestamp: Date;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
type HistoryEvent = SlashEvent | RewardEvent;
|
|
58
|
-
|
|
59
|
-
export class ValidatorHistoryAction extends StakingAction {
|
|
60
|
-
constructor() {
|
|
61
|
-
super();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private getNetworkForHistory(config: StakingConfig): GenLayerChain {
|
|
65
|
-
if (config.network) {
|
|
66
|
-
const network = BUILT_IN_NETWORKS[config.network];
|
|
67
|
-
if (!network) {
|
|
68
|
-
throw new Error(`Unknown network: ${config.network}`);
|
|
69
|
-
}
|
|
70
|
-
return network;
|
|
71
|
-
}
|
|
72
|
-
// Check global config
|
|
73
|
-
const globalNetwork = this.getConfig().network;
|
|
74
|
-
if (globalNetwork && BUILT_IN_NETWORKS[globalNetwork]) {
|
|
75
|
-
return BUILT_IN_NETWORKS[globalNetwork];
|
|
76
|
-
}
|
|
77
|
-
return BUILT_IN_NETWORKS["localnet"];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async execute(options: ValidatorHistoryOptions): Promise<void> {
|
|
81
|
-
this.startSpinner("Fetching validator history...");
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
// Check network - localnet doesn't support eth_getLogs
|
|
85
|
-
const chain = this.getNetworkForHistory(options);
|
|
86
|
-
if (chain.id === 808080) {
|
|
87
|
-
this.failSpinner("validator-history requires testnet-asimov (localnet doesn't support event logs)");
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const client = await this.getReadOnlyStakingClient(options);
|
|
92
|
-
const validatorAddress = options.validator || (await this.getSignerAddress());
|
|
93
|
-
|
|
94
|
-
// Verify it's a validator
|
|
95
|
-
const isValidator = await client.isValidator(validatorAddress as Address);
|
|
96
|
-
if (!isValidator) {
|
|
97
|
-
this.failSpinner(`Address ${validatorAddress} is not a validator`);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
this.setSpinnerText("Fetching contract addresses...");
|
|
102
|
-
|
|
103
|
-
// Get addresses
|
|
104
|
-
const stakingAddress = client.getStakingContract().address;
|
|
105
|
-
const slashingAddress = await client.getSlashingAddress();
|
|
106
|
-
|
|
107
|
-
// Create public client for log fetching
|
|
108
|
-
const publicClient = createPublicClient({
|
|
109
|
-
chain,
|
|
110
|
-
transport: http(chain.rpcUrls.default.http[0]),
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// Determine epoch range for filtering
|
|
114
|
-
const epochInfo = await client.getEpochInfo();
|
|
115
|
-
const currentEpoch = epochInfo.currentEpoch;
|
|
116
|
-
const defaultEpochs = 10n;
|
|
117
|
-
|
|
118
|
-
let minEpoch: bigint | null = null;
|
|
119
|
-
let fromBlock: bigint | "earliest" = "earliest";
|
|
120
|
-
|
|
121
|
-
if (options.fromBlock) {
|
|
122
|
-
// Explicit block takes precedence
|
|
123
|
-
fromBlock = BigInt(options.fromBlock);
|
|
124
|
-
} else if (options.fromEpoch) {
|
|
125
|
-
// Filter by starting epoch
|
|
126
|
-
minEpoch = BigInt(options.fromEpoch);
|
|
127
|
-
} else if (options.all) {
|
|
128
|
-
// Fetch all history (warn user)
|
|
129
|
-
console.log(chalk.yellow("Warning: Fetching all history from genesis. This may be slow for long-lived validators."));
|
|
130
|
-
console.log(chalk.yellow("Consider using --epochs <n> or --from-epoch <n> for faster queries.\n"));
|
|
131
|
-
} else {
|
|
132
|
-
// Default: last N epochs
|
|
133
|
-
const numEpochs = options.epochs ? BigInt(options.epochs) : defaultEpochs;
|
|
134
|
-
minEpoch = currentEpoch > numEpochs ? currentEpoch - numEpochs : 0n;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const limit = options.limit ? parseInt(options.limit) : 50;
|
|
138
|
-
|
|
139
|
-
this.setSpinnerText("Fetching slash events...");
|
|
140
|
-
|
|
141
|
-
// Fetch slash events (indexed by validator)
|
|
142
|
-
const slashLogs = await publicClient.getLogs({
|
|
143
|
-
address: slashingAddress as `0x${string}`,
|
|
144
|
-
event: SLASH_EVENT_ABI,
|
|
145
|
-
args: {validator: validatorAddress as `0x${string}`},
|
|
146
|
-
fromBlock,
|
|
147
|
-
toBlock: "latest",
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
this.setSpinnerText("Fetching reward events...");
|
|
151
|
-
|
|
152
|
-
// Fetch reward events (not indexed, need to filter client-side)
|
|
153
|
-
const rewardLogs = await publicClient.getLogs({
|
|
154
|
-
address: stakingAddress,
|
|
155
|
-
event: REWARD_EVENT_ABI,
|
|
156
|
-
fromBlock,
|
|
157
|
-
toBlock: "latest",
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// Filter rewards to this validator
|
|
161
|
-
const filteredRewardLogs = rewardLogs.filter(
|
|
162
|
-
log => (log.args as any).validator?.toLowerCase() === validatorAddress.toLowerCase()
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
// Get unique block numbers to fetch timestamps
|
|
166
|
-
const allLogs = [...slashLogs, ...filteredRewardLogs];
|
|
167
|
-
const uniqueBlocks = [...new Set(allLogs.map(l => l.blockNumber))];
|
|
168
|
-
|
|
169
|
-
this.setSpinnerText("Fetching block timestamps...");
|
|
170
|
-
|
|
171
|
-
// Fetch block timestamps in batches
|
|
172
|
-
const blockTimestamps = new Map<bigint, Date>();
|
|
173
|
-
const BATCH_SIZE = 10;
|
|
174
|
-
for (let i = 0; i < uniqueBlocks.length; i += BATCH_SIZE) {
|
|
175
|
-
const batch = uniqueBlocks.slice(i, i + BATCH_SIZE);
|
|
176
|
-
const blocks = await Promise.all(
|
|
177
|
-
batch.map(blockNumber => publicClient.getBlock({blockNumber}))
|
|
178
|
-
);
|
|
179
|
-
blocks.forEach(block => {
|
|
180
|
-
blockTimestamps.set(block.number, new Date(Number(block.timestamp) * 1000));
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Transform to typed events
|
|
185
|
-
let slashEvents: SlashEvent[] = slashLogs.map(log => ({
|
|
186
|
-
type: "slash" as const,
|
|
187
|
-
epoch: (log.args as any).epoch as bigint,
|
|
188
|
-
txId: (log.args as any).txId as string,
|
|
189
|
-
percentage: (log.args as any).percentage as bigint,
|
|
190
|
-
blockNumber: log.blockNumber,
|
|
191
|
-
timestamp: blockTimestamps.get(log.blockNumber) || new Date(0),
|
|
192
|
-
}));
|
|
193
|
-
|
|
194
|
-
let rewardEvents: RewardEvent[] = filteredRewardLogs.map(log => ({
|
|
195
|
-
type: "reward" as const,
|
|
196
|
-
epoch: (log.args as any).epoch as bigint,
|
|
197
|
-
validatorRewards: (log.args as any).validatorRewards as bigint,
|
|
198
|
-
delegatorRewards: (log.args as any).delegatorRewards as bigint,
|
|
199
|
-
blockNumber: log.blockNumber,
|
|
200
|
-
timestamp: blockTimestamps.get(log.blockNumber) || new Date(0),
|
|
201
|
-
}));
|
|
202
|
-
|
|
203
|
-
// Filter by epoch if specified
|
|
204
|
-
if (minEpoch !== null) {
|
|
205
|
-
slashEvents = slashEvents.filter(e => e.epoch >= minEpoch!);
|
|
206
|
-
rewardEvents = rewardEvents.filter(e => e.epoch >= minEpoch!);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Combine and sort by block number descending
|
|
210
|
-
const allEvents: HistoryEvent[] = [...slashEvents, ...rewardEvents];
|
|
211
|
-
allEvents.sort((a, b) => Number(b.blockNumber - a.blockNumber));
|
|
212
|
-
|
|
213
|
-
// Apply limit
|
|
214
|
-
const limitedEvents = allEvents.slice(0, limit);
|
|
215
|
-
|
|
216
|
-
// Calculate totals
|
|
217
|
-
const totalValidatorRewards = rewardEvents.reduce((sum, e) => sum + e.validatorRewards, 0n);
|
|
218
|
-
const totalDelegatorRewards = rewardEvents.reduce((sum, e) => sum + e.delegatorRewards, 0n);
|
|
219
|
-
|
|
220
|
-
this.stopSpinner();
|
|
221
|
-
|
|
222
|
-
// Display results
|
|
223
|
-
if (limitedEvents.length === 0) {
|
|
224
|
-
console.log(chalk.yellow("\nNo history events found for this validator.\n"));
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Format timestamp as datetime
|
|
229
|
-
const formatTime = (date: Date): string => {
|
|
230
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
231
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
232
|
-
const hours = String(date.getHours()).padStart(2, "0");
|
|
233
|
-
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
234
|
-
return `${month}-${day} ${hours}:${minutes}`;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
// Create table
|
|
238
|
-
const table = new Table({
|
|
239
|
-
head: [
|
|
240
|
-
chalk.cyan("Time"),
|
|
241
|
-
chalk.cyan("Epoch"),
|
|
242
|
-
chalk.cyan("Type"),
|
|
243
|
-
chalk.cyan("Details"),
|
|
244
|
-
chalk.cyan("GL TxId / Block"),
|
|
245
|
-
],
|
|
246
|
-
style: {head: [], border: []},
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
for (const event of limitedEvents) {
|
|
250
|
-
if (event.type === "slash") {
|
|
251
|
-
const pct = Number(event.percentage) / 100; // basis points to %
|
|
252
|
-
table.push([
|
|
253
|
-
formatTime(event.timestamp),
|
|
254
|
-
event.epoch.toString(),
|
|
255
|
-
chalk.red("SLASH"),
|
|
256
|
-
`${pct.toFixed(2)}%`,
|
|
257
|
-
event.txId,
|
|
258
|
-
]);
|
|
259
|
-
} else {
|
|
260
|
-
const valReward = client.formatStakingAmount(event.validatorRewards);
|
|
261
|
-
const delReward = client.formatStakingAmount(event.delegatorRewards);
|
|
262
|
-
table.push([
|
|
263
|
-
formatTime(event.timestamp),
|
|
264
|
-
event.epoch.toString(),
|
|
265
|
-
chalk.green("REWARD"),
|
|
266
|
-
`Val: ${valReward}, Del: ${delReward}`,
|
|
267
|
-
`block ${event.blockNumber}`,
|
|
268
|
-
]);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
console.log("");
|
|
273
|
-
console.log(chalk.bold(`History for ${validatorAddress}`));
|
|
274
|
-
console.log(table.toString());
|
|
275
|
-
console.log("");
|
|
276
|
-
|
|
277
|
-
// Summary
|
|
278
|
-
const epochRangeInfo = minEpoch !== null
|
|
279
|
-
? `epochs ${minEpoch}-${currentEpoch}`
|
|
280
|
-
: options.fromBlock
|
|
281
|
-
? `from block ${options.fromBlock}`
|
|
282
|
-
: "all epochs";
|
|
283
|
-
console.log(chalk.gray("Summary:"));
|
|
284
|
-
console.log(chalk.gray(` Range: ${epochRangeInfo}`));
|
|
285
|
-
console.log(chalk.gray(` Slash events: ${slashEvents.length}`));
|
|
286
|
-
console.log(chalk.gray(` Reward events: ${rewardEvents.length}`));
|
|
287
|
-
console.log(chalk.gray(` Total validator rewards: ${client.formatStakingAmount(totalValidatorRewards)}`));
|
|
288
|
-
console.log(chalk.gray(` Total delegator rewards: ${client.formatStakingAmount(totalDelegatorRewards)}`));
|
|
289
|
-
if (allEvents.length > limit) {
|
|
290
|
-
console.log(chalk.gray(` (showing ${limit} of ${allEvents.length} events)`));
|
|
291
|
-
}
|
|
292
|
-
console.log(chalk.gray(` Use --all to fetch complete history, --epochs <n> for last N epochs`));
|
|
293
|
-
console.log("");
|
|
294
|
-
} catch (error: any) {
|
|
295
|
-
this.failSpinner("Failed to get validator history", error.message || error);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import {StakingAction, StakingConfig} from "./StakingAction";
|
|
2
|
-
import type {Address} from "genlayer-js/types";
|
|
3
|
-
|
|
4
|
-
export interface ValidatorJoinOptions extends StakingConfig {
|
|
5
|
-
amount: string;
|
|
6
|
-
operator?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class ValidatorJoinAction extends StakingAction {
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async execute(options: ValidatorJoinOptions): Promise<void> {
|
|
15
|
-
this.startSpinner("Creating a new validator...");
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
const client = await this.getStakingClient(options);
|
|
19
|
-
const amount = this.parseAmount(options.amount);
|
|
20
|
-
const signerAddress = await this.getSignerAddress();
|
|
21
|
-
|
|
22
|
-
this.setSpinnerText(`Creating validator with ${this.formatAmount(amount)} stake...`);
|
|
23
|
-
this.log(` From: ${signerAddress}`);
|
|
24
|
-
if (options.operator) {
|
|
25
|
-
this.log(` Operator: ${options.operator}`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const result = await client.validatorJoin({
|
|
29
|
-
amount,
|
|
30
|
-
operator: options.operator as Address | undefined,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const output = {
|
|
34
|
-
transactionHash: result.transactionHash,
|
|
35
|
-
validatorWallet: result.validatorWallet,
|
|
36
|
-
amount: result.amount,
|
|
37
|
-
operator: result.operator,
|
|
38
|
-
blockNumber: result.blockNumber.toString(),
|
|
39
|
-
gasUsed: result.gasUsed.toString(),
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
this.succeedSpinner("Validator created successfully!", output);
|
|
43
|
-
} catch (error: any) {
|
|
44
|
-
this.failSpinner("Failed to create validator", error.message || error);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {StakingAction, StakingConfig} from "./StakingAction";
|
|
2
|
-
import type {Address} from "genlayer-js/types";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
|
|
5
|
-
export interface ValidatorPrimeOptions extends StakingConfig {
|
|
6
|
-
validator: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class ValidatorPrimeAction extends StakingAction {
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async execute(options: ValidatorPrimeOptions): Promise<void> {
|
|
15
|
-
this.startSpinner("Priming validator...");
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
const client = await this.getStakingClient(options);
|
|
19
|
-
|
|
20
|
-
this.setSpinnerText(`Priming validator ${options.validator}...`);
|
|
21
|
-
|
|
22
|
-
const result = await client.validatorPrime({validator: options.validator as Address});
|
|
23
|
-
|
|
24
|
-
const output = {
|
|
25
|
-
transactionHash: result.transactionHash,
|
|
26
|
-
validator: options.validator,
|
|
27
|
-
blockNumber: result.blockNumber.toString(),
|
|
28
|
-
gasUsed: result.gasUsed.toString(),
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
this.succeedSpinner("Validator primed for next epoch!", output);
|
|
32
|
-
} catch (error: any) {
|
|
33
|
-
this.failSpinner("Failed to prime validator", error.message || error);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async primeAll(options: StakingConfig): Promise<void> {
|
|
38
|
-
this.startSpinner("Fetching validators...");
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
const client = await this.getStakingClient(options);
|
|
42
|
-
|
|
43
|
-
// Get all validators from tree
|
|
44
|
-
this.setSpinnerText("Fetching validators...");
|
|
45
|
-
const allValidators = await this.getAllValidatorsFromTree(options);
|
|
46
|
-
|
|
47
|
-
this.stopSpinner();
|
|
48
|
-
console.log(`\nPriming ${allValidators.length} validators:\n`);
|
|
49
|
-
|
|
50
|
-
let succeeded = 0;
|
|
51
|
-
let skipped = 0;
|
|
52
|
-
|
|
53
|
-
for (const addr of allValidators) {
|
|
54
|
-
process.stdout.write(` ${addr} ... `);
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
const result = await client.validatorPrime({validator: addr});
|
|
58
|
-
console.log(chalk.green(`primed ${result.transactionHash}`));
|
|
59
|
-
succeeded++;
|
|
60
|
-
} catch (error: any) {
|
|
61
|
-
const msg = error.message || String(error);
|
|
62
|
-
const shortErr = msg.length > 60 ? msg.slice(0, 57) + "..." : msg;
|
|
63
|
-
console.log(chalk.gray(`skipped: ${shortErr}`));
|
|
64
|
-
skipped++;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
console.log(`\n${chalk.green(`${succeeded} primed`)}, ${chalk.gray(`${skipped} skipped`)}\n`);
|
|
69
|
-
} catch (error: any) {
|
|
70
|
-
this.failSpinner("Failed to prime validators", error.message || error);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|