-
Notifications
You must be signed in to change notification settings - Fork 33
feat: staking commands #417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0ffdf04
25dfac8
a7e46fb
af7ecc5
b71be9b
3bd6310
7c3f916
811ff37
7c9c17d
d8062a1
250f58a
3791004
29566b0
6d5475b
3137753
572b672
ca0d89b
2ee0849
ec0f9ca
ac58202
6701508
fc74ae5
a10b435
1ae6763
0cb221a
e47d9cf
9c7c2b1
8f55b78
aba5b11
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| import { Command, Option } from "commander"; | ||
| import { ethers } from "ethers"; | ||
| import { z } from "zod"; | ||
|
|
||
| import { STAKING_PRECOMPILE } from "../../../../src/constants/addresses"; | ||
| import { namePkRefineRule } from "../../../../types/shared.schema"; | ||
| import { handleError, validateAndParseSchema } from "../../../../utils"; | ||
| import type { | ||
| ConfirmTxOptionsSubset, | ||
| SetupTxOptionsSubset, | ||
| } from "../../../../utils/zetachain.command.helpers"; | ||
| import { | ||
| confirmZetachainTransaction, | ||
| setupZetachainTransaction, | ||
| } from "../../../../utils/zetachain.command.helpers"; | ||
| import stakingArtifact from "./staking.json"; | ||
|
|
||
| const STAKING_ABI = (stakingArtifact as { abi: unknown }) | ||
| .abi as ethers.InterfaceAbi; | ||
|
|
||
| const delegateOptionsSchema = z | ||
| .object({ | ||
| amount: z.string(), | ||
| chainId: z.string().optional(), | ||
| name: z.string().default("default"), | ||
| privateKey: z.string().optional(), | ||
| rpc: z.string().optional(), | ||
| validator: z.string(), | ||
| yes: z.boolean().default(false), | ||
| }) | ||
| .refine(namePkRefineRule); | ||
|
|
||
| type DelegateOptions = z.infer<typeof delegateOptionsSchema>; | ||
|
|
||
| const main = async (options: DelegateOptions) => { | ||
| try { | ||
| const { signer } = setupZetachainTransaction({ | ||
| chainId: options.chainId, | ||
| name: options.name, | ||
| privateKey: options.privateKey, | ||
| rpc: options.rpc, | ||
| } satisfies SetupTxOptionsSubset); | ||
|
|
||
| const delegatorAddress = await signer.getAddress(); | ||
| const amountWei = ethers.parseEther(options.amount); | ||
|
|
||
| console.log(`Staking delegation details: | ||
| Delegator: ${delegatorAddress} | ||
| Validator: ${options.validator} | ||
| Amount: ${options.amount} ZETA | ||
| `); | ||
|
|
||
| const isConfirmed = await confirmZetachainTransaction({ | ||
| yes: options.yes, | ||
| } satisfies ConfirmTxOptionsSubset); | ||
| if (!isConfirmed) return; | ||
|
|
||
| const iface = new ethers.Interface(STAKING_ABI); | ||
| const data = iface.encodeFunctionData("delegate", [ | ||
| delegatorAddress, | ||
| options.validator, | ||
| amountWei, | ||
| ]); | ||
|
|
||
| const tx = await signer.sendTransaction({ | ||
| data, | ||
| to: STAKING_PRECOMPILE, | ||
| value: amountWei, | ||
| }); | ||
|
Comment on lines
+65
to
+69
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainDouble-specifying amount (calldata + msg.value) may be wrong for this ABI. Please verify. You encode amount as a parameter and also send value: amountWei. Depending on the staking precompile ABI, only one may be required. Run to confirm the delegate signature and mutability: If inputs do not include an amount (or stateMutability is payable), drop the calldata amount and rely on msg.value; otherwise, keep the calldata amount and set value: 0n. 🏁 Script executed: #!/bin/bash
# Locate staking.json and inspect the `delegate` function signature.
set -euo pipefail
fd -a 'staking.json' | while read -r f; do
echo "File: $f"
jq -r '
.abi
| map(select(.type=="function" and .name=="delegate"))
| .[] | {name, stateMutability, inputs, outputs}
' "$f"
doneLength of output: 553 Drop 🤖 Prompt for AI Agents |
||
|
|
||
| const receipt = await tx.wait(); | ||
| console.log("Transaction hash:", tx.hash ?? receipt?.hash); | ||
| } catch (error) { | ||
| handleError({ | ||
| context: "Error during staking delegation", | ||
| error, | ||
| shouldThrow: false, | ||
| }); | ||
| process.exit(1); | ||
| } | ||
| }; | ||
|
|
||
| export const delegateCommand = new Command("delegate").summary( | ||
| "Delegate ZETA to a validator via the staking precompile" | ||
| ); | ||
|
|
||
| delegateCommand | ||
| .addOption( | ||
| new Option( | ||
| "--validator <valoper>", | ||
| "Validator operator address (zetavaloper...)" | ||
| ).makeOptionMandatory() | ||
| ) | ||
| .addOption( | ||
| new Option( | ||
| "--amount <amount>", | ||
| "Amount of ZETA to delegate" | ||
| ).makeOptionMandatory() | ||
| ) | ||
| .addOption( | ||
| new Option("--name <name>", "Account name") | ||
| .default("default") | ||
| .conflicts(["private-key"]) | ||
| ) | ||
| .addOption( | ||
| new Option("--private-key <key>", "Private key for signing").conflicts([ | ||
| "name", | ||
| ]) | ||
| ) | ||
| .addOption(new Option("--rpc <url>", "ZetaChain RPC URL")) | ||
| .addOption(new Option("--chain-id <id>", "ZetaChain chain ID")) | ||
| .addOption(new Option("--yes", "Skip confirmation").default(false)) | ||
| .action(async (rawOptions) => { | ||
| const options = validateAndParseSchema(rawOptions, delegateOptionsSchema, { | ||
| exitOnError: true, | ||
| }); | ||
| await main(options); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { Command } from "commander"; | ||
|
|
||
| import { listCommand } from "./list"; | ||
| import { showCommand } from "./show"; | ||
|
|
||
| export const delegationsCommand = new Command("delegations") | ||
| .summary("Delegations-related queries") | ||
| .addCommand(listCommand) | ||
| .addCommand(showCommand) | ||
| .helpCommand(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validator address must be normalized (accept bech32 valoper and 0x).
You pass options.validator as-is. CLI examples use zetavaloper… bech32, while the precompile likely expects a 20‑byte EVM address. Normalize input to 0x… (and checksum) before encoding.
Apply this diff in-place to use a normalized address:
Add this helper and imports outside the range:
🤖 Prompt for AI Agents