Skip to content

Commit

Permalink
add token transfer action
Browse files Browse the repository at this point in the history
  • Loading branch information
Trisfald committed Apr 30, 2024
1 parent 10a1976 commit 6b0fcb7
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 7 deletions.
11 changes: 8 additions & 3 deletions src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ use derive_more::{Constructor, Display};
use crate::AppError;

#[derive(Debug, Constructor, Default, Clone, Display)]
#[display("{}:{}", signer_id, network)]
#[display("{}:{}:{}", signer_id, buddy_id, network)]
pub struct Account {
pub signer_id: String,
pub buddy_id: String,
pub network: String,
}

Expand All @@ -16,10 +17,14 @@ impl FromStr for Account {

fn from_str(s: &str) -> Result<Self, Self::Err> {
let split: Vec<_> = s.split(':').collect();
if split.len() != 2 {
if split.len() != 3 {
Err(AppError::AccountParseError(s.to_string()))
} else {
Ok(Account::new(split[0].to_string(), split[1].to_string()))
Ok(Account::new(
split[0].to_string(),
split[1].to_string(),
split[2].to_string(),
))
}
}
}
5 changes: 3 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ pub enum Command {
/// Args needed to execute transactions.
#[derive(Debug, Args, Default, Clone)]
pub struct ExecArgs {
/// A list of <NEAR wallet account>:<network>.
#[arg(env)]
/// A list of <NEAR wallet account>:<NEAR wallet buddy account>:<network>.
/// Main account is used to sign transactions. Buddy account is the receiver of token transfers (where applicable)
#[arg(env, verbatim_doc_comment)]
pub accounts: Vec<Account>,
#[clap(env, short, long, default_value = foo())]
/// Path to the location storing the account keys. Defaults to the user's directory.
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub enum AppError {
NoMatchedTransaction(Regex),
#[error("transaction error({0})")]
TransactionError(String),
#[error("cannot parse account and network from '{0}'")]
#[error("cannot parse signer account, buddy account and network from '{0}'")]
AccountParseError(String),
#[error("unknown error")]
Unknown,
Expand Down
8 changes: 7 additions & 1 deletion src/transaction/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use tracing::{info, warn};
use crate::{
config::RunArgs,
metrics::{Labels, Metrics},
transaction::token_transfer::TokenTransfer,
Account, AppError, Transaction,
};

Expand All @@ -31,6 +32,7 @@ impl Engine {
}

add_transaction!(SelfTokenTransfer);
add_transaction!(TokenTransfer);

Engine { transactions }
}
Expand Down Expand Up @@ -200,7 +202,11 @@ mod tests {
fn create_test_run_args() -> RunArgs {
RunArgs {
exec_args: ExecArgs {
accounts: vec![Account::new(String::new(), NETWORK.to_string())],
accounts: vec![Account::new(
String::new(),
String::new(),
NETWORK.to_string(),
)],
key_path: String::new(),
},
period: Duration::from_millis(1),
Expand Down
1 change: 1 addition & 0 deletions src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{Account, AppError};
pub mod engine;

mod self_token_transfer;
mod token_transfer;

#[derive(Debug, PartialEq, Eq, Hash, Display, From, Deref, Constructor, Clone)]
pub struct TransactionKind(String);
Expand Down
67 changes: 67 additions & 0 deletions src/transaction/token_transfer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use crate::{Account, AppError, Transaction, TransactionOutcome};
use async_trait::async_trait;
use tokio::{process::Command, time::Instant};
use tracing::{debug, warn};

use super::TransactionKind;

pub struct TokenTransfer {}

#[async_trait]
impl Transaction for TokenTransfer {
fn kind(&self) -> TransactionKind {
TransactionKind("token_transfer".to_string())
}

async fn execute(
&self,
account: &Account,
key_path: &str,
) -> Result<TransactionOutcome, AppError> {
let now = Instant::now();
let output_result = Command::new("near")
.args([
"tokens",
&account.signer_id,
"send-near",
&account.buddy_id,
"1 yoctoNEAR",
"network-config",
&account.network,
"sign-with-access-key-file",
&format!(
"{}/.near-credentials/{}/{}.json",
key_path, account.network, account.signer_id
),
"send",
])
.output()
.await;
let elapsed = now.elapsed();

match output_result {
Ok(output) => {
if output.status.success() {
debug!(
"successful call to near token send:\n{}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
Ok(TransactionOutcome::new(elapsed))
} else {
warn!(
"failure during call to near token send:\n{}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
Err(AppError::TransactionError(
"near token send-near failed".to_string(),
))
}
}
Err(err) => Err(AppError::TransactionError(format!(
"near CLI invocation failure ({err})"
))),
}
}
}

0 comments on commit 6b0fcb7

Please sign in to comment.