Skip to content

Commit 1b8bb02

Browse files
committed
syncing with the latest testnet changes
1 parent 83b9826 commit 1b8bb02

File tree

14 files changed

+9134
-8400
lines changed

14 files changed

+9134
-8400
lines changed

tooling/sparta/src/admins/manageValidators.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import { ChainInfoService } from "../services/chaininfo-service.js";
88
import { paginate } from "../utils/pagination.js";
99
import { ValidatorService } from "../services/validator-service.js";
10+
import { validateAddress } from "../utils/inputValidator.js";
1011

1112
export const EXCLUDED_VALIDATORS = [
1213
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
@@ -100,8 +101,18 @@ export default {
100101
.setDescription("The validator to remove")
101102
.setRequired(true)
102103
)
104+
)
105+
.addSubcommand((subcommand) =>
106+
subcommand
107+
.setName("fund")
108+
.setDescription("Fund a validator with Sepolia ETH")
109+
.addStringOption((option) =>
110+
option
111+
.setName("address")
112+
.setDescription("The validator to fund")
113+
.setRequired(true)
114+
)
103115
),
104-
105116
execute: async (interaction: ChatInputCommandInteraction) => {
106117
await interaction.deferReply({
107118
flags: MessageFlags.Ephemeral,
@@ -158,19 +169,36 @@ export default {
158169
return `Failed`;
159170
}
160171

161-
// Basic address validation
162-
if (!address.match(/^0x[a-fA-F0-9]{40}$/)) {
163-
return interaction.reply({
172+
if (validateAddress(address)) {
173+
await interaction.editReply({
164174
content: "Please provide a valid Ethereum address.",
165-
flags: MessageFlags.Ephemeral,
166175
});
176+
return `Failed`;
167177
}
168178

169179
await ValidatorService.addValidator(address);
170180
await interaction.editReply({
171181
content: `Successfully added validator address: ${address}`,
172182
});
173183
return `Added validator ${address}`;
184+
} else if (interaction.options.getSubcommand() === "fund") {
185+
const address = interaction.options.getString("address");
186+
if (!address) {
187+
await interaction.editReply({
188+
content: "Please provide an address to fund",
189+
});
190+
return `Failed`;
191+
}
192+
if (validateAddress(address)) {
193+
await interaction.editReply({
194+
content: "Please provide a valid Ethereum address.",
195+
});
196+
return `Failed`;
197+
}
198+
await ValidatorService.fundValidator(address);
199+
await interaction.editReply({
200+
content: `Successfully funded validator ${address}`,
201+
});
174202
}
175203
return;
176204
} catch (error) {

tooling/sparta/src/commands/getChainInfo.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import {
22
SlashCommandBuilder,
33
ChatInputCommandInteraction,
44
MessageFlags,
5+
TextChannel,
6+
DiscordAPIError,
57
} from "discord.js";
68
import { ChainInfoService } from "../services/chaininfo-service.js";
79

@@ -11,9 +13,8 @@ export default {
1113
.setDescription("Get chain info"),
1214

1315
execute: async (interaction: ChatInputCommandInteraction) => {
14-
await interaction.deferReply({
15-
flags: MessageFlags.Ephemeral,
16-
});
16+
// Defer reply without ephemeral flag to make it visible to everyone
17+
await interaction.deferReply();
1718

1819
try {
1920
const {
@@ -24,6 +25,58 @@ export default {
2425
proposerNow,
2526
} = await ChainInfoService.getInfo();
2627

28+
// Delete previous get-info messages from the bot in this channel
29+
try {
30+
if (interaction.channel && !interaction.channel.isDMBased()) {
31+
const channel = interaction.channel as TextChannel;
32+
const messages = await channel.messages.fetch({
33+
limit: 15,
34+
});
35+
36+
// Filter for bot messages that look like chain info responses
37+
// and aren't the current interaction's response
38+
const botMessages = messages.filter(
39+
(m) =>
40+
m.author.id === interaction.client.user?.id &&
41+
m.content.includes("Pending block:") &&
42+
m.content.includes("Proven block:") &&
43+
m.content.includes("Current epoch:") &&
44+
!m.flags.has(MessageFlags.Ephemeral) &&
45+
// Ensure we don't delete the message we're about to send
46+
m.id !== interaction.id
47+
);
48+
49+
if (botMessages.size > 0) {
50+
try {
51+
// Try bulk delete first (only works for messages less than 14 days old)
52+
await channel.bulkDelete(botMessages);
53+
} catch (error) {
54+
// If bulk delete fails (e.g., messages are too old), delete individually
55+
if (
56+
error instanceof DiscordAPIError &&
57+
error.code === 50034
58+
) {
59+
for (const message of botMessages.values()) {
60+
try {
61+
await message.delete();
62+
} catch (deleteError) {
63+
console.error(
64+
"Error deleting individual message:",
65+
deleteError
66+
);
67+
}
68+
}
69+
} else {
70+
throw error;
71+
}
72+
}
73+
}
74+
}
75+
} catch (error) {
76+
console.error("Error deleting previous messages:", error);
77+
// Continue with the command even if message deletion fails
78+
}
79+
2780
await interaction.editReply({
2881
content: `Pending block: ${pendingBlockNum}\nProven block: ${provenBlockNum}\nCurrent epoch: ${currentEpoch}\nCurrent slot: ${currentSlot}\nProposer now: ${proposerNow}`,
2982
});

tooling/sparta/src/services/validator-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class ValidatorService {
2626

2727
static async fundValidator(address: string): Promise<string> {
2828
try {
29-
const command = `cast send --value ${process.env.ETHEREUM_VALUE} --rpc-url ${process.env.ETHEREUM_HOST} --chain-id ${process.env.ETHEREUM_CHAIN_ID} --private-key ${process.env.MINTER_PRIVATE_KEY} ${address}`;
29+
const command = `cast send --value ${process.env.FUNDER_AMOUNT} --rpc-url ${process.env.ETHEREUM_HOST} --chain-id ${process.env.L1_CHAIN_ID} --private-key ${process.env.FUNDER_ADDRESS_PRIVATE_KEY} ${address}`;
3030

3131
const { stdout, stderr } = await execAsync(command);
3232

0 commit comments

Comments
 (0)