Skip to content

Commit

Permalink
refactor: Updated reconstruct-transaction command (#281)
Browse files Browse the repository at this point in the history
  • Loading branch information
FroVolod authored Dec 21, 2023
1 parent 4b056e1 commit 32dff46
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 95 deletions.
36 changes: 36 additions & 0 deletions docs/GUIDE.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -1796,6 +1796,7 @@ Contract state (proof):
### transaction - Operate transactions

- [view-status](#view-status---View-a-transaction-status)
- [reconstruct-transaction](#reconstruct-transaction---Use-any-existing-transaction-from-the-chain-to-construct-NEAR-CLI-command-helpful-tool-for-re-submitting-similar-transactions)
- [construct-transaction](#construct-transaction---Construct-a-new-transaction)
- [sign-transaction](#sign-transaction---Sign-previously-prepared-unsigned-transaction)
- [send-signed-transaction](#send-signed-transaction---Send-a-signed-transaction)
Expand Down Expand Up @@ -1972,6 +1973,41 @@ Transaction status: FinalExecutionOutcomeWithReceiptView {
</a>
</details>

#### reconstruct-transaction - Use any existing transaction from the chain to construct NEAR CLI command (helpful tool for re-submitting similar transactions)

Let's consider an example when it is necessary to repeat a previously completed transaction:
```txt
near transaction \
reconstruct-transaction GDoinMecpvnqahzJz9tXLxYycznL4cAoxKTPEnJZ3ank \
network-config testnet
```

<details><summary><i>The result of this command will be as follows:</i></summary>

```txt
Transaction GDoinMecpvnqahzJz9tXLxYycznL4cAoxKTPEnJZ3ank:
signer_id: volodymyr.testnet
receiver_id: qweqweqwe.volodymyr.testnet
actions:
-- create account: qweqweqwe.volodymyr.testnet
-- transfer deposit: 100 NEAR
-- add access key:
public key: ed25519:AgVv8qjZ7yix3pTo7BimT1zoDYUSTGcg73RBssC5JMRf
nonce: 0
permission: FullAccess
Here is your console command to run archive transaction. You can to edit it or re-run:
near transaction construct-transaction volodymyr.testnet qweqweqwe.volodymyr.testnet add-action create-account add-action transfer '100 NEAR' add-action add-key grant-full-access use-manually-provided-public-key ed25519:AgVv8qjZ7yix3pTo7BimT1zoDYUSTGcg73RBssC5JMRf skip network-config testnet
```
</details>

<details><summary><i>Demonstration of the command in interactive mode</i></summary>
<a href="https://asciinema.org/a/lw5MEk8sJ1NGPMNWpuVfjLpAT?autoplay=1&t=1&speed=2">
<img src="https://asciinema.org/a/lw5MEk8sJ1NGPMNWpuVfjLpAT.png" width="836"/>
</a>
</details>

#### construct-transaction - Construct a new transaction

Let's consider an example when it is necessary to perform several actions within one transaction:
Expand Down
36 changes: 36 additions & 0 deletions docs/GUIDE.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -1808,6 +1808,7 @@ Contract state (proof):
### transaction - Operate transactions

- [view-status](#view-status---View-a-transaction-status)
- [reconstruct-transaction](#reconstruct-transaction---Use-any-existing-transaction-from-the-chain-to-construct-NEAR-CLI-command-helpful-tool-for-re-submitting-similar-transactions)
- [construct-transaction](#construct-transaction---Construct-a-new-transaction)
- [sign-transaction](#sign-transaction---Sign-previously-prepared-unsigned-transaction)
- [send-signed-transaction](#send-signed-transaction---Send-a-signed-transaction)
Expand Down Expand Up @@ -1984,6 +1985,41 @@ Transaction status: FinalExecutionOutcomeWithReceiptView {
</a>
</details>

#### reconstruct-transaction - Use any existing transaction from the chain to construct NEAR CLI command (helpful tool for re-submitting similar transactions)

Рассмотрим пример, когда необходимо повторить выполненную ранее транзакцию:
```txt
near transaction \
reconstruct-transaction GDoinMecpvnqahzJz9tXLxYycznL4cAoxKTPEnJZ3ank \
network-config testnet
```

<details><summary><i>Результат выполнения команды</i></summary>

```txt
Transaction GDoinMecpvnqahzJz9tXLxYycznL4cAoxKTPEnJZ3ank:
signer_id: volodymyr.testnet
receiver_id: qweqweqwe.volodymyr.testnet
actions:
-- create account: qweqweqwe.volodymyr.testnet
-- transfer deposit: 100 NEAR
-- add access key:
public key: ed25519:AgVv8qjZ7yix3pTo7BimT1zoDYUSTGcg73RBssC5JMRf
nonce: 0
permission: FullAccess
Here is your console command to run archive transaction. You can to edit it or re-run:
near transaction construct-transaction volodymyr.testnet qweqweqwe.volodymyr.testnet add-action create-account add-action transfer '100 NEAR' add-action add-key grant-full-access use-manually-provided-public-key ed25519:AgVv8qjZ7yix3pTo7BimT1zoDYUSTGcg73RBssC5JMRf skip network-config testnet
```
</details>

<details><summary>Демонстрация работы команды в интерактивном режиме</summary>
<a href="https://asciinema.org/a/lw5MEk8sJ1NGPMNWpuVfjLpAT?autoplay=1&t=1&speed=2">
<img src="https://asciinema.org/a/lw5MEk8sJ1NGPMNWpuVfjLpAT.png" width="836"/>
</a>
</details>

#### construct-transaction - Construct a new transaction

Рассмотрим пример, когда необходимо выполнить несколько действий в рамках одной транзакции:
Expand Down
205 changes: 110 additions & 95 deletions src/commands/transaction/reconstruct_transaction/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use color_eyre::eyre::{Context, ContextCompat};
use color_eyre::eyre::Context;
use interactive_clap::ToCliArgs;

use crate::common::JsonRpcClientExt;
Expand All @@ -9,13 +9,13 @@ use crate::common::JsonRpcClientExt;
pub struct TransactionInfo {
/// Enter the hash of the transaction you want to use as a template:
transaction_hash: crate::types::crypto_hash::CryptoHash,
/// What is the name of the network?
#[interactive_clap(skip_default_input_arg)]
network_name: String,
#[interactive_clap(named_arg)]
/// Select network
network_config: crate::network::Network,
}

#[derive(Clone)]
pub struct TransactionInfoContext;
pub struct TransactionInfoContext(crate::network::NetworkContext);

impl TransactionInfoContext {
pub fn from_previous_context(
Expand All @@ -25,107 +25,122 @@ impl TransactionInfoContext {
use super::construct_transaction::{add_action_1, skip_action, CliConstructTransaction};
use super::{CliTransactionActions, CliTransactionCommands};

let networks = previous_context.config.network_connection;
let network_config = networks
.get(&scope.network_name)
.wrap_err("Failed to get network config!")?
.clone();
let query_view_transaction_status = network_config
.json_rpc_client()
.blocking_call(
near_jsonrpc_client::methods::tx::RpcTransactionStatusRequest {
transaction_info:
near_jsonrpc_client::methods::tx::TransactionInfo::TransactionId {
hash: scope.transaction_hash.into(),
account_id: "near".parse::<near_primitives::types::AccountId>()?,
},
},
)
.wrap_err_with(|| {
format!(
"Failed to fetch query for view transaction on network <{}>",
network_config.network_name
)
})?;
let on_after_getting_network_callback: crate::network::OnAfterGettingNetworkCallback =
std::sync::Arc::new({
let transaction_hash = scope.transaction_hash;

let mut prepopulated_transaction = crate::commands::PrepopulatedTransaction {
signer_id: query_view_transaction_status.transaction.signer_id,
receiver_id: query_view_transaction_status.transaction.receiver_id,
actions: query_view_transaction_status
.transaction
.actions
.into_iter()
.map(near_primitives::transaction::Action::try_from)
.collect::<Result<Vec<near_primitives::transaction::Action>, _>>()
.expect("Internal error: can not convert the action_view to action."),
};
move |network_config| {
let query_view_transaction_status = network_config
.json_rpc_client()
.blocking_call(
near_jsonrpc_client::methods::tx::RpcTransactionStatusRequest {
transaction_info:
near_jsonrpc_client::methods::tx::TransactionInfo::TransactionId {
hash: transaction_hash.into(),
account_id: "near".parse::<near_primitives::types::AccountId>()?,
},
},
)
.wrap_err_with(|| {
format!(
"Failed to fetch query for view transaction on network <{}>",
network_config.network_name
)
})?;

eprintln!(
"\nTransaction {}:\n",
query_view_transaction_status.transaction.hash
);
crate::common::print_unsigned_transaction(&prepopulated_transaction);
eprintln!();
let mut prepopulated_transaction = crate::commands::PrepopulatedTransaction {
signer_id: query_view_transaction_status.transaction.signer_id,
receiver_id: query_view_transaction_status.transaction.receiver_id,
actions: query_view_transaction_status
.transaction
.actions
.into_iter()
.map(near_primitives::transaction::Action::try_from)
.collect::<Result<Vec<near_primitives::transaction::Action>, _>>()
.expect("Internal error: can not convert the action_view to action."),
};

if prepopulated_transaction.actions.len() == 1 {
if let near_primitives::transaction::Action::Delegate(signed_delegate_action) =
&prepopulated_transaction.actions[0]
{
prepopulated_transaction = crate::commands::PrepopulatedTransaction {
signer_id: signed_delegate_action.delegate_action.sender_id.clone(),
receiver_id: signed_delegate_action.delegate_action.receiver_id.clone(),
actions: signed_delegate_action.delegate_action.get_actions(),
};
}
}
eprintln!(
"\nTransaction {}:\n",
query_view_transaction_status.transaction.hash
);
crate::common::print_unsigned_transaction(&prepopulated_transaction);
eprintln!();

let cmd = crate::commands::CliTopLevelCommand::Transaction(CliTransactionCommands {
transaction_actions: Some(CliTransactionActions::ConstructTransaction(
CliConstructTransaction {
sender_account_id: Some(prepopulated_transaction.signer_id.into()),
receiver_account_id: Some(prepopulated_transaction.receiver_id.into()),
next_actions: None,
},
)),
});
let mut cmd_cli_args = cmd.to_cli_args();
if prepopulated_transaction.actions.len() == 1 {
if let near_primitives::transaction::Action::Delegate(
signed_delegate_action,
) = &prepopulated_transaction.actions[0]
{
prepopulated_transaction = crate::commands::PrepopulatedTransaction {
signer_id: signed_delegate_action.delegate_action.sender_id.clone(),
receiver_id: signed_delegate_action
.delegate_action
.receiver_id
.clone(),
actions: signed_delegate_action.delegate_action.get_actions(),
};
}
}

for transaction_action in prepopulated_transaction.actions {
let next_actions =
add_action_1::CliNextAction::AddAction(add_action_1::add_action::CliAddAction {
action: action_transformation(transaction_action)?,
});
cmd_cli_args.extend(next_actions.to_cli_args());
}
let cmd =
crate::commands::CliTopLevelCommand::Transaction(CliTransactionCommands {
transaction_actions: Some(CliTransactionActions::ConstructTransaction(
CliConstructTransaction {
sender_account_id: Some(
prepopulated_transaction.signer_id.into(),
),
receiver_account_id: Some(
prepopulated_transaction.receiver_id.into(),
),
next_actions: None,
},
)),
});
let mut cmd_cli_args = cmd.to_cli_args();

let skip_action = add_action_1::CliNextAction::Skip(skip_action::CliSkipAction {
network_config: Some(
skip_action::ClapNamedArgNetworkForTransactionArgsForSkipAction::NetworkConfig(
crate::network_for_transaction::CliNetworkForTransactionArgs {
network_name: Some(scope.network_name.clone()),
transaction_signature_options: None,
},
),
),
});
cmd_cli_args.extend(skip_action.to_cli_args());
for transaction_action in prepopulated_transaction.actions {
let next_actions = add_action_1::CliNextAction::AddAction(
add_action_1::add_action::CliAddAction {
action: action_transformation(transaction_action)?,
},
);
cmd_cli_args.extend(next_actions.to_cli_args());
}

let near_cli_exec_path = crate::common::get_near_exec_path();
eprintln!("Here is your console command to run archive transaction. You can to edit it or re-run:");
eprintln!(
"{}\n",
shell_words::join(std::iter::once(near_cli_exec_path).chain(cmd_cli_args))
);
let skip_action = add_action_1::CliNextAction::Skip(skip_action::CliSkipAction {
network_config: Some(
skip_action::ClapNamedArgNetworkForTransactionArgsForSkipAction::NetworkConfig(
crate::network_for_transaction::CliNetworkForTransactionArgs {
network_name: Some(network_config.network_name.clone()),
transaction_signature_options: None,
},
),
),
});
cmd_cli_args.extend(skip_action.to_cli_args());

let near_cli_exec_path = crate::common::get_near_exec_path();
eprintln!("Here is your console command to run archive transaction. You can to edit it or re-run:");
eprintln!(
"{}\n",
shell_words::join(std::iter::once(near_cli_exec_path).chain(cmd_cli_args))
);
Ok(())
}
});

Ok(Self)
Ok(Self(crate::network::NetworkContext {
config: previous_context.config,
interacting_with_account_ids: vec![],
on_after_getting_network_callback,
}))
}
}

impl TransactionInfo {
fn input_network_name(
context: &crate::GlobalContext,
) -> color_eyre::eyre::Result<Option<String>> {
crate::common::input_network_name(&context.config, &[])
impl From<TransactionInfoContext> for crate::network::NetworkContext {
fn from(item: TransactionInfoContext) -> Self {
item.0
}
}

Expand Down

0 comments on commit 32dff46

Please sign in to comment.