icepick workflow cosmos transfer

This commit is contained in:
Ryan Heywood 2025-01-22 04:09:43 -05:00
parent db5ca73d10
commit d00a67e0b7
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
3 changed files with 115 additions and 22 deletions

View File

@ -161,11 +161,10 @@ pub fn default_chains() -> Vec<Blockchain> {
.coin_decimals(6) .coin_decimals(6)
.coin_gecko_id("unknown") .coin_gecko_id("unknown")
.build(); .build();
// NOTE: high is listed as 0.03 on devnet, but simulating tx actually cost 30915 tkyve.
let tkyve_gas = GasPriceStep::builder() let tkyve_gas = GasPriceStep::builder()
.low(0.01) .low(0.01)
.average(0.05) .average(0.025)
.high(0.1) .high(0.03)
.build(); .build();
chains.push( chains.push(

View File

@ -32,7 +32,7 @@ pub struct GetWalletAddress {
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct GetAccountInfo { pub struct GetAccountData {
account_id: String, account_id: String,
blockchain_config: coin_denoms::Blockchain, blockchain_config: coin_denoms::Blockchain,
@ -57,7 +57,7 @@ pub struct Transfer {
// TODO: find a way to simulate transaction and calculate gas necessary // TODO: find a way to simulate transaction and calculate gas necessary
// for now, 0.01KYVE seems to be a reasonable mainnet number? // for now, 0.01KYVE seems to be a reasonable mainnet number?
// for testing purposes, i'm gonna go much lower. 0.0001. // for testing purposes, i'm gonna go much lower. 0.0001.
gas: Option<String>, gas_factor: Option<String>,
blockchain_config: coin_denoms::Blockchain, blockchain_config: coin_denoms::Blockchain,
} }
@ -66,8 +66,8 @@ pub struct Transfer {
pub struct Sign { pub struct Sign {
fee: remote_serde::Fee, fee: remote_serde::Fee,
tx_messages: Vec<Any>, tx_messages: Vec<Any>,
account_number: String, account_number: u64,
sequence_number: String, sequence_number: u64,
blockchain_config: coin_denoms::Blockchain, blockchain_config: coin_denoms::Blockchain,
} }
@ -94,7 +94,7 @@ pub enum Operation {
GetChainInfo(GetChainInfo), GetChainInfo(GetChainInfo),
GenerateWallet(GenerateWallet), GenerateWallet(GenerateWallet),
GetWalletAddress(GetWalletAddress), GetWalletAddress(GetWalletAddress),
GetAccountInfo(GetAccountInfo), GetAccountData(GetAccountData),
AwaitFunds(AwaitFunds), AwaitFunds(AwaitFunds),
Transfer(Transfer), Transfer(Transfer),
Sign(Sign), Sign(Sign),
@ -188,7 +188,7 @@ impl Module for Cosmos {
.argument(&address_prefix); .argument(&address_prefix);
let get_account_info = Operation::builder() let get_account_info = Operation::builder()
.name("get-account-info") .name("get-account-data")
.description("Get the account number and sequence number for an account.") .description("Get the account number and sequence number for an account.")
.build() .build()
.argument( .argument(
@ -255,8 +255,8 @@ impl Module for Cosmos {
) )
.argument( .argument(
&Argument::builder() &Argument::builder()
.name("gas") .name("gas_factor")
.description("The amount of gas to supply.") .description("The factor to multiply the default gas amount by.")
.r#type(ArgumentType::Optional) .r#type(ArgumentType::Optional)
.build(), .build(),
); );
@ -336,7 +336,7 @@ impl Module for Cosmos {
} }
})) }))
} }
Operation::GetAccountInfo(GetAccountInfo { Operation::GetAccountData(GetAccountData {
account_id, account_id,
blockchain_config, blockchain_config,
}) => { }) => {
@ -437,7 +437,7 @@ impl Module for Cosmos {
to_address, to_address,
from_account: _, from_account: _,
from_address, from_address,
gas: _, gas_factor,
blockchain_config, blockchain_config,
}) => { }) => {
// Check if given denom is min denom or normal and adjust accordingly // Check if given denom is min denom or normal and adjust accordingly
@ -449,6 +449,13 @@ impl Module for Cosmos {
panic!("{denom} not in {blockchain_config:?}"); panic!("{denom} not in {blockchain_config:?}");
}; };
let gas_factor = gas_factor
.as_deref()
.map(f64::from_str)
.transpose()
.unwrap()
.unwrap_or(1.0);
let amount = f64::from_str(&amount).unwrap(); let amount = f64::from_str(&amount).unwrap();
let adjusted_amount = if relevant_denom.coin_denom == denom { let adjusted_amount = if relevant_denom.coin_denom == denom {
amount * 10f64.powi(i32::from(relevant_denom.coin_decimals)) amount * 10f64.powi(i32::from(relevant_denom.coin_decimals))
@ -474,11 +481,23 @@ impl Module for Cosmos {
.to_any() .to_any()
.unwrap(); .unwrap();
let expected_gas = 100_000u64;
// convert gas "price" to minimum denom,
// multiply by amount of gas required,
// multiply by gas factor if necessary.
let expected_fee = blockchain_config.gas_price_step.high
// * dbg!(10f64.powi(relevant_denom.coin_decimals as i32))
* expected_gas as f64
* gas_factor;
let fee_coin = cosmrs::Coin {
denom: relevant_denom.coin_minimal_denom.parse().unwrap(),
amount: expected_fee as u128,
};
let fee = Fee::from_amount_and_gas( let fee = Fee::from_amount_and_gas(
coin, fee_coin,
(blockchain_config.gas_price_step.high expected_gas,
* 10f64.powi(relevant_denom.coin_decimals as i32))
as u64,
); );
#[allow(clippy::identity_op)] #[allow(clippy::identity_op)]
@ -508,11 +527,6 @@ impl Module for Cosmos {
let fee = cosmrs::tx::Fee::from(&fee); let fee = cosmrs::tx::Fee::from(&fee);
let tx_body = BodyBuilder::new().msgs(tx_messages).finish(); let tx_body = BodyBuilder::new().msgs(tx_messages).finish();
// TODO: these should be gained by the `broadcast` workflow, similar to
// how nonce data is acquired in Solana
let account_number: u64 = account_number.parse().unwrap();
let sequence_number: u64 = sequence_number.parse().unwrap();
let auth_info = let auth_info =
SignerInfo::single_direct(Some(privkey.public_key()), sequence_number) SignerInfo::single_direct(Some(privkey.public_key()), sequence_number)
.auth_info(fee); .auth_info(fee);

View File

@ -225,3 +225,83 @@ inputs = { transaction = "signed_transaction" }
name = "cosmos" name = "cosmos"
derivation_prefix = "m/44'/118'/0'" derivation_prefix = "m/44'/118'/0'"
algorithm = "Secp256k1" algorithm = "Secp256k1"
[[module.workflow]]
name = "transfer"
inputs = ["from_address", "to_address", "asset_name", "chain_name", "asset_amount"]
[[module.workflow.step]]
# NOTE: chain_name can't be discoverable by filtering from asset_name, since
# some asset devnets reuse the name. There's no difference between KYVE on Kyve
# or Korellia (devnet).
type = "cosmos-get-chain-info"
inputs = { chain_name = "chain_name" }
outputs = { blockchain_config = "blockchain_config" }
[[module.workflow.step]]
type = "internal-load-file"
values = { filename = "account_info.json" }
outputs = { account_number = "account_number", sequence_number = "sequence_number" }
[[module.workflow.step]]
type = "cosmos-transfer"
[module.workflow.step.inputs]
from_address = "from_address"
to_address = "to_address"
amount = "asset_amount"
denom = "asset_name"
blockchain_config = "blockchain_config"
[module.workflow.step.outputs]
fee = "fee"
tx_messages = "tx_messages"
[[module.workflow.step]]
type = "cosmos-sign"
[module.workflow.step.inputs]
fee = "fee"
tx_messages = "tx_messages"
account_number = "account_number"
sequence_number = "sequence_number"
blockchain_config = "blockchain_config"
[module.workflow.step.outputs]
transaction = "signed_transaction"
[[module.workflow.step]]
type = "internal-save-file"
values = { filename = "transaction.json" }
inputs = { transaction = "signed_transaction" }
[[module.workflow]]
name = "broadcast"
# NOTE: For the purpose of Cosmos, the nonce is a direct part of the signer's
# account.
inputs = ["nonce_address", "chain_name"]
[[module.workflow.step]]
type = "cosmos-get-chain-info"
inputs = { chain_name = "chain_name" }
outputs = { blockchain_config = "blockchain_config" }
[[module.workflow.step]]
type = "cosmos-get-account-data"
inputs = { account_id = "nonce_address", blockchain_config = "blockchain_config" }
outputs = { account_number = "account_number", sequence_number = "sequence_number" }
[[module.workflow.step]]
type = "internal-save-file"
values = { filename = "account_info.json" }
inputs = { account_number = "account_number", sequence_number = "sequence_number" }
[[module.workflow.step]]
type = "internal-load-file"
values = { filename = "transaction.json" }
outputs = { transaction = "transaction" }
[[module.workflow.step]]
type = "cosmos-broadcast"
inputs = { blockchain_config = "blockchain_config", transaction = "transaction" }
outputs = { status = "status", url = "url", error = "error", error_code = "error_code" }