icepick workflow cosmos withdraw-rewards

This commit is contained in:
Ryan Heywood 2025-01-30 12:36:43 -05:00
parent b5034586cc
commit e49d6be339
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
1 changed files with 90 additions and 1 deletions

View File

@ -93,6 +93,15 @@ pub struct Withdraw {
blockchain_config: coin_denoms::Blockchain,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct WithdrawRewards {
delegate_address: String,
validator_address: String,
gas_factor: Option<String>,
blockchain_config: coin_denoms::Blockchain,
}
#[derive(Deserialize, Serialize, Debug)]
pub struct Sign {
fee: remote_serde::Fee,
@ -132,6 +141,7 @@ pub enum Operation {
Transfer(Transfer),
Stake(Stake),
Withdraw(Withdraw),
WithdrawRewards(WithdrawRewards),
Sign(Sign),
Broadcast(Broadcast),
}
@ -362,7 +372,7 @@ impl Module for Cosmos {
let withdraw = Operation::builder()
.name("withdraw")
.description("Delegate coins to a specified validator.")
.description("Withdraw coins delegated to a specified validator.")
.build()
.argument(
&Argument::builder()
@ -400,6 +410,32 @@ impl Module for Cosmos {
.build(),
);
let withdraw_rewards = Operation::builder()
.name("withdraw-rewards")
.description("Withdraw staking rewards from a validator.")
.build()
.argument(
&Argument::builder()
.name("delegate_address")
.description("The address holding funds to be withdrawn.")
.r#type(ArgumentType::Required)
.build(),
)
.argument(
&Argument::builder()
.name("validator_address")
.description("The address of the validator operator to withdraw from.")
.r#type(ArgumentType::Required)
.build(),
)
.argument(
&Argument::builder()
.name("gas_factor")
.description("The factor to multiply the default gas amount by.")
.r#type(ArgumentType::Optional)
.build(),
);
let sign = Operation::builder()
.name("sign")
.description("Sign a previously-generated transaction.")
@ -436,6 +472,7 @@ impl Module for Cosmos {
sign,
stake,
withdraw,
withdraw_rewards,
broadcast,
]
}
@ -806,6 +843,58 @@ impl Module for Cosmos {
"derivation_accounts": [0u32 | 1 << 31],
}))
}
Operation::WithdrawRewards(WithdrawRewards {
delegate_address,
validator_address,
gas_factor,
blockchain_config,
}) => {
let gas_denom = blockchain_config.fee_currencies[0].currency.clone();
let gas_factor = gas_factor
.as_deref()
.map(f64::from_str)
.transpose()
.unwrap()
.unwrap_or(1.0);
let delegate_id = AccountId::from_str(&delegate_address).unwrap();
let validator_id = AccountId::from_str(&validator_address).unwrap();
let msg_withdraw_rewards = cosmrs::distribution::MsgWithdrawDelegatorReward {
delegator_address: delegate_id,
validator_address: validator_id,
}
.to_any()
.unwrap();
let expected_gas = 250_000u64;
// convert gas "price" to minimum denom,
// multiply by amount of gas required,
// multiply by gas factor
let expected_fee =
blockchain_config.gas_price_step.high * expected_gas as f64 * gas_factor;
let fee_coin = cosmrs::Coin {
denom: gas_denom.coin_minimal_denom.parse().unwrap(),
amount: expected_fee as u128,
};
let fee = Fee::from_amount_and_gas(fee_coin, expected_gas);
#[allow(clippy::identity_op)]
Ok(serde_json::json!({
"blob": {
"fee": remote_serde::Fee::from(&fee),
// TODO: Body does not implement Serialize and
// needs to be constructed in Sign
"tx_messages": [msg_withdraw_rewards],
// re-export, but in general this should be copied over
// using workflows
},
"derivation_accounts": [0u32 | 1 << 31],
}))
}
Operation::Transfer(Transfer {
amount,
denom,