From e4ea4bc21be45276a60f86aba152395f56ad5007 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Roy <102650062+so-kkroy22@users.noreply.github.com> Date: Fri, 18 Oct 2024 20:31:02 +0530 Subject: [PATCH] [Moonshot/issues][#1027] Integrate multisig command (#109) * integrate multisig tool * fix async trait usage * correct transactionoption in executewithpayload command * provide option to set account metadata --- .../src/aptos_framework_sdk_builder.rs | 36 ++-- crates/aptos/src/account/multisig_account.rs | 158 ++++++++++++++++++ 2 files changed, 176 insertions(+), 18 deletions(-) diff --git a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs index 49ea455ff750b..ad305a018ee0d 100644 --- a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs +++ b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs @@ -1049,9 +1049,9 @@ pub enum EntryFunctionCall { VestingWithoutStakingCreateVestingContractWithAmounts { shareholders: Vec, - amounts: Vec, - schedule_numerator: Vec, - schedule_denominator: u64, + shares: Vec, + vesting_numerators: Vec, + vesting_denominator: u64, start_timestamp_secs: u64, period_duration: u64, withdrawal_address: AccountAddress, @@ -1768,18 +1768,18 @@ impl EntryFunctionCall { }, VestingWithoutStakingCreateVestingContractWithAmounts { shareholders, - amounts, - schedule_numerator, - schedule_denominator, + shares, + vesting_numerators, + vesting_denominator, start_timestamp_secs, period_duration, withdrawal_address, contract_creation_seed, } => vesting_without_staking_create_vesting_contract_with_amounts( shareholders, - amounts, - schedule_numerator, - schedule_denominator, + shares, + vesting_numerators, + vesting_denominator, start_timestamp_secs, period_duration, withdrawal_address, @@ -4885,9 +4885,9 @@ pub fn vesting_without_staking_admin_withdraw( pub fn vesting_without_staking_create_vesting_contract_with_amounts( shareholders: Vec, - amounts: Vec, - schedule_numerator: Vec, - schedule_denominator: u64, + shares: Vec, + vesting_numerators: Vec, + vesting_denominator: u64, start_timestamp_secs: u64, period_duration: u64, withdrawal_address: AccountAddress, @@ -4905,9 +4905,9 @@ pub fn vesting_without_staking_create_vesting_contract_with_amounts( vec![], vec![ bcs::to_bytes(&shareholders).unwrap(), - bcs::to_bytes(&amounts).unwrap(), - bcs::to_bytes(&schedule_numerator).unwrap(), - bcs::to_bytes(&schedule_denominator).unwrap(), + bcs::to_bytes(&shares).unwrap(), + bcs::to_bytes(&vesting_numerators).unwrap(), + bcs::to_bytes(&vesting_denominator).unwrap(), bcs::to_bytes(&start_timestamp_secs).unwrap(), bcs::to_bytes(&period_duration).unwrap(), bcs::to_bytes(&withdrawal_address).unwrap(), @@ -6857,9 +6857,9 @@ mod decoder { Some( EntryFunctionCall::VestingWithoutStakingCreateVestingContractWithAmounts { shareholders: bcs::from_bytes(script.args().get(0)?).ok()?, - amounts: bcs::from_bytes(script.args().get(1)?).ok()?, - schedule_numerator: bcs::from_bytes(script.args().get(2)?).ok()?, - schedule_denominator: bcs::from_bytes(script.args().get(3)?).ok()?, + shares: bcs::from_bytes(script.args().get(1)?).ok()?, + vesting_numerators: bcs::from_bytes(script.args().get(2)?).ok()?, + vesting_denominator: bcs::from_bytes(script.args().get(3)?).ok()?, start_timestamp_secs: bcs::from_bytes(script.args().get(4)?).ok()?, period_duration: bcs::from_bytes(script.args().get(5)?).ok()?, withdrawal_address: bcs::from_bytes(script.args().get(6)?).ok()?, diff --git a/crates/aptos/src/account/multisig_account.rs b/crates/aptos/src/account/multisig_account.rs index f77a321f88edc..f20a2db2b1a0b 100644 --- a/crates/aptos/src/account/multisig_account.rs +++ b/crates/aptos/src/account/multisig_account.rs @@ -1,6 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +use anyhow::anyhow; use crate::common::{ types::{ CliCommand, CliError, CliTypedResult, EntryFunctionArguments, MultisigAccount, @@ -25,6 +26,7 @@ use clap::Parser; use move_core_types::{ident_str, language_storage::ModuleId}; use serde::Serialize; use serde_json::json; +use supra_aptos::{SupraCommand, SupraCommandArguments}; /// Create a new multisig account (v2) on-chain. /// @@ -42,6 +44,13 @@ pub struct Create { /// transaction. #[clap(long)] pub(crate) num_signatures_required: u64, + /// Allow the multisig account to update its own metadata key and value + /// Metadata Key + #[clap(long)] + metadata_keys: Vec, + /// Metadata Value + #[clap(long)] + metadata_values: Vec, #[clap(flatten)] pub(crate) txn_options: TransactionOptions, } @@ -106,6 +115,40 @@ impl CliCommand for Create { } } +#[async_trait] +impl SupraCommand for Create { + async fn supra_command_arguments(self) -> anyhow::Result { + if self.metadata_keys.len() != self.metadata_values.len() { + return Err(anyhow!("Not all metadata key has a metadata value.")) + }; + let metadata_key = self.metadata_keys.iter() + .map(|k| to_bytes(k)) + .collect::, _>>()?; + + let metadata_value = self.metadata_values.iter() + .map(|v| to_bytes(v)) + .collect::, _>>()?; + + let payload = aptos_stdlib::multisig_account_create_with_owners( + self.additional_owners, + self.num_signatures_required, + metadata_key, + metadata_value, + self.timeout_duration, + ); + + Ok( + SupraCommandArguments { + payload, + sender_account: self.txn_options.sender_account, + profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options), + rest_options: supra_aptos::RestOptions::from(self.txn_options.rest_options), + gas_options: supra_aptos::GasOptions::from(self.txn_options.gas_options), + } + ) + } +} + /// Propose a new multisig transaction. /// /// As one of the owners of the multisig, propose a new transaction. This also implicitly approves @@ -151,6 +194,32 @@ impl CliCommand for CreateTransaction { } } +#[async_trait] +impl SupraCommand for CreateTransaction { + async fn supra_command_arguments(self) -> anyhow::Result { + let multisig_transaction_payload_bytes = + to_bytes::(&self.entry_function_args.try_into()?)?; + let payload = if self.store_hash_only { + aptos_stdlib::multisig_account_create_transaction_with_hash( + self.multisig_account.multisig_address, + HashValue::sha3_256_of(&multisig_transaction_payload_bytes).to_vec(), + ) + } else { + aptos_stdlib::multisig_account_create_transaction( + self.multisig_account.multisig_address, + multisig_transaction_payload_bytes, + ) + }; + Ok(SupraCommandArguments{ + payload, + sender_account: self.txn_options.sender_account, + profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options), + rest_options: supra_aptos::RestOptions::from(self.txn_options.rest_options), + gas_options: supra_aptos::GasOptions::from(self.txn_options.gas_options), + }) + } +} + /// Verify entry function matches on-chain transaction proposal. #[derive(Debug, Parser)] pub struct VerifyProposal { @@ -260,6 +329,26 @@ impl CliCommand for Approve { } } +#[async_trait] +impl SupraCommand for Approve { + async fn supra_command_arguments(self) -> anyhow::Result { + let payload = aptos_stdlib::multisig_account_approve_transaction( + self.multisig_account_with_sequence_number + .multisig_account + .multisig_address, + self.multisig_account_with_sequence_number.sequence_number, + ); + + Ok(SupraCommandArguments { + payload, + sender_account: self.txn_options.sender_account, + profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options), + rest_options: supra_aptos::RestOptions::from(self.txn_options.rest_options), + gas_options: supra_aptos::GasOptions::from(self.txn_options.gas_options), + }) + } +} + /// Reject a multisig transaction. /// /// As one of the owners of the multisig, reject a transaction proposed for the multisig. @@ -292,6 +381,25 @@ impl CliCommand for Reject { } } +#[async_trait] +impl SupraCommand for Reject { + async fn supra_command_arguments(self) -> anyhow::Result { + let payload = aptos_stdlib::multisig_account_reject_transaction( + self.multisig_account_with_sequence_number + .multisig_account + .multisig_address, + self.multisig_account_with_sequence_number.sequence_number, + ); + Ok(SupraCommandArguments { + payload, + sender_account: self.txn_options.sender_account, + profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options), + rest_options: supra_aptos::RestOptions::from(self.txn_options.rest_options), + gas_options: supra_aptos::GasOptions::from(self.txn_options.gas_options), + }) + } +} + /// Execute a proposed multisig transaction that has a full payload stored on-chain. #[derive(Debug, Parser)] pub struct Execute { @@ -318,6 +426,23 @@ impl CliCommand for Execute { } } +#[async_trait] +impl SupraCommand for Execute { + async fn supra_command_arguments(self) -> anyhow::Result { + let payload = TransactionPayload::Multisig(Multisig { + multisig_address: self.multisig_account.multisig_address, + transaction_payload: None, + }); + Ok(SupraCommandArguments { + payload, + sender_account: self.txn_options.sender_account, + profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options), + rest_options: supra_aptos::RestOptions::from(self.txn_options.rest_options), + gas_options: supra_aptos::GasOptions::from(self.txn_options.gas_options), + }) + } +} + /// Execute a proposed multisig transaction that has only a payload hash stored on-chain. #[derive(Debug, Parser)] pub struct ExecuteWithPayload { @@ -345,6 +470,23 @@ impl CliCommand for ExecuteWithPayload { } } +#[async_trait] +impl SupraCommand for ExecuteWithPayload { + async fn supra_command_arguments(self) -> anyhow::Result { + let payload = TransactionPayload::Multisig(Multisig { + multisig_address: self.execute.multisig_account.multisig_address, + transaction_payload: Some(self.entry_function_args.try_into()?), + }); + Ok(SupraCommandArguments { + payload, + sender_account: self.execute.txn_options.sender_account, + profile_options: supra_aptos::ProfileOptions::from(self.execute.txn_options.profile_options), + rest_options: supra_aptos::RestOptions::from(self.execute.txn_options.rest_options), + gas_options: supra_aptos::GasOptions::from(self.execute.txn_options.gas_options), + }) + } +} + /// Remove a proposed multisig transaction. /// /// The transaction to be removed needs to have as many rejections as the number of signatures @@ -372,3 +514,19 @@ impl CliCommand for ExecuteReject { .map(|inner| inner.into()) } } + +#[async_trait] +impl SupraCommand for ExecuteReject { + async fn supra_command_arguments(self) -> anyhow::Result { + let payload = aptos_stdlib::multisig_account_execute_rejected_transaction( + self.multisig_account.multisig_address, + ); + Ok(SupraCommandArguments { + payload, + sender_account: self.txn_options.sender_account, + profile_options: supra_aptos::ProfileOptions::from(self.txn_options.profile_options), + rest_options: supra_aptos::RestOptions::from(self.txn_options.rest_options), + gas_options: supra_aptos::GasOptions::from(self.txn_options.gas_options), + }) + } +}