Skip to content

Commit

Permalink
mocked transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
0xPrimata committed Jun 13, 2024
1 parent 41038b6 commit bb1660c
Show file tree
Hide file tree
Showing 11 changed files with 1,019 additions and 388 deletions.
1,112 changes: 739 additions & 373 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ members = [
"networks/suzuka/suzuka-client",
"networks/suzuka/suzuka-config",
"networks/suzuka/suzuka-full-node",
"util/commander"
]

[workspace.package]
Expand Down Expand Up @@ -60,6 +61,8 @@ mcr-settlement-client = { path = "protocol-units/settlement/mcr/client" }
mcr-settlement-manager = { path = "protocol-units/settlement/mcr/manager" }
## types
movement-types = { path = "util/movement-types" }
## util
commander = { path = "util/commander" }

# Serialization and Deserialization
borsh = { version = "0.10" } # todo: internalize jmt and bump
Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
celestia-node
celestia-app
monza-aptos
jq
];

# Specific version of toolchain
Expand Down
8 changes: 8 additions & 0 deletions networks/suzuka/suzuka-client/.aptos/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
profiles:
default:
private_key: "0xfbc0596f14bd008b20269a52e22311842453ccd3dd64575bc656dc8e755244b7"
public_key: "0xbe11803a40d33723d0a294cb657dd2477af4c31cae019f1e4bd783084033d1f6"
account: 00da3c48fe5d426966ae33945eff05cdbc5fb9a986c92d26a9d7665d99efdeff
rest_url: "http://0.0.0.0:30731/"
faucet_url: "http://0.0.0.0:30733/"
4 changes: 4 additions & 0 deletions networks/suzuka/suzuka-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ url = { workspace = true }
rand = { workspace = true }
maptos-execution-util = { workspace = true }
commander = { workspace = true }
buildtime = { workspace = true }
buildtime-helpers = { workspace = true }
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"

[lints]
workspace = true
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "1.0.0"
authors = []

[addresses]
resource_roulette = '0xd1939537bbfd08a0fdee25d8216f5696e90c090a7641046d6c606b0aeec77b4a'
resource_roulette = '_'

[dev-addresses]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh

# Initializes an account if keys are not present
initialize_output=$(echo -ne '\n' | aptos init --network custom --rest-url $NODE_URL --faucet-url $FAUCET_URL --assume-yes)
echo "$initialize_output"

aptos move test --package-dir src/tests/complex-alice --named-addresses resource_roulette=default

aptos move compile --package-dir src/tests/complex-alice --named-addresses resource_roulette=default
153 changes: 139 additions & 14 deletions networks/suzuka/suzuka-client/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
use crate::{
coin_client::CoinClient,
rest_client::{Client, FaucetClient},
types::LocalAccount,
types::{LocalAccount,
chain_id::ChainId,
transaction::Script, //SignedTransaction, TransactionArgument},
}
};
use anyhow::{Context, Result};
use anyhow::Context;

use once_cell::sync::Lazy;
use std::str::FromStr;
use url::Url;
use commander::run_command;
use buildtime_helpers::cargo::cargo_workspace;
use std::path::PathBuf;
use serde::Deserialize;
use std::fs;
use aptos_sdk::{crypto::ed25519::Ed25519PrivateKey, rest_client::Account};
use aptos_sdk::crypto::ed25519::Ed25519PublicKey;
use aptos_sdk::crypto::ValidCryptoMaterialStringExt;
use aptos_sdk::move_types::ident_str;
use aptos_sdk::move_types::identifier::Identifier;
use aptos_sdk::move_types::language_storage::ModuleId;
use aptos_sdk::move_types::language_storage::StructTag;
use aptos_sdk::move_types::language_storage::TypeTag;
use aptos_sdk::rest_client::FaucetClient;
use aptos_sdk::transaction_builder::TransactionBuilder;
use aptos_sdk::types::account_address::AccountAddress;
use aptos_sdk::types::move_utils::MemberId;
use aptos_sdk::types::transaction::authenticator::AuthenticationKey;
use aptos_sdk::types::transaction::EntryFunction;
use aptos_sdk::types::transaction::TransactionPayload;
use aptos_sdk::transaction_builder::TransactionFactory;


static SUZUKA_CONFIG: Lazy<maptos_execution_util::config::Config> = Lazy::new(|| {
maptos_execution_util::config::Config::try_from_env()
Expand All @@ -28,7 +53,7 @@ static FAUCET_URL: Lazy<Url> = Lazy::new(|| {
// <:!:section_1c

#[tokio::test]
async fn test_example_interaction() -> Result<()> {
async fn test_example_interaction() -> Result<(), anyhow::Error> {
// :!:>section_1a
let rest_client = Client::new(NODE_URL.clone());
let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone()); // <:!:section_1a
Expand Down Expand Up @@ -134,17 +159,117 @@ async fn test_example_interaction() -> Result<()> {
Ok(())
}

#[derive(Debug, Deserialize)]
struct Config {
profiles: Profiles,
}

#[derive(Debug, Deserialize)]
struct Profiles {
default: DefaultProfile,
}

#[derive(Debug, Deserialize)]
struct DefaultProfile {
account: String,
private_key: String,
}

async fn send_tx(
client: Client,
account: Account,
module_address: AccountAddress,
module_name: &str,
function_name: &str,
type_args: Vec<TypeTag>,
args: Vec<TransactionArgument>,
) -> Result<Result, anyhow::Error> {
//get account sequence numner
let account_address = account.authentication_key.account_address();
let account_rpc = client.get_account(account_address).await.unwrap();
let sequence_number = account_rpc.inner().sequence_number;
println!("sequence_number: {sequence_number:?}", );
let identifier = Identifier::new(function_name)?;
let payload = TransactionPayload::EntryFunction(EntryFunction::new(
module_address,
identifier,
type_args,
args,
));

let sign_tx = account.sign_transaction(raw_tx);
let base_max_gas_amount = signed_transaction.max_gas_amount();
let base_gas_unit_price = signed_transaction.gas_unit_price();
let base_expiration_timestamp_secs = signed_transaction.expiration_timestamp_secs();

let tx_receipt_data = client.submit_and_wait_bcs(&signed_transaction).await?;
println!("tx_receipt_data: {tx_receipt_data:?}", );

Ok(tx_receipt_data)
}

#[tokio::test]
async fn complex_alice() {
const resource_roulette : &str = "default";
let init = format!("aptos init --rpc-url {} --faucet-url {} --assume-yes", NODE_URL.clone(), FAUCET_URL.clone());
let enter = "\ne";
let test = format!("aptos move test -named-addresses resource_roulette={}", resource_roulette);
let command = format!("aptos move publish --named-addresses resource_roulette={}", resource_roulette);

const init_output : String = run_command(&init, &[]).await;
const enter_output : String = run_command(&enter, &[]).await;
const test_output : String = run_command(&test, &[]).await;
const command_output : String = run_command(&command, &[]).await;
pub async fn test_complex_alice() -> Result<(), anyhow::Error> {

std::env::set_var("NODE_URL", NODE_URL.clone().as_str());
std::env::set_var("FAUCET_URL", FAUCET_URL.clone().as_str());
let root: PathBuf = cargo_workspace()?;
let additional_path = "networks/suzuka/suzuka-client/src/tests/complex-alice/";
let combined_path = root.join(additional_path);

// Convert the combined path to a string
let test = combined_path.to_string_lossy();
println!("{}", test);

// let args = format!("echo -ne '\\n' | aptos init --network custom --rest-url {} --faucet-url {} --assume-yes", node_url, faucet_url);
let init_output = run_command("/bin/bash", &[format!("{}{}", test, "deploy.sh").as_str()]).await?;
println!("{}",init_output);

let yaml_content = fs::read_to_string(".aptos/config.yaml")?;

let config: Config = serde_yaml::from_str(&yaml_content)?;

// Access the `account` field
let account = &config.profiles.default.account;
let private_key_import = &config.profiles.default.private_key;
let private_key = Ed25519PrivateKey::from_encoded_string(
private_key_import
)?;

let public_key = Ed25519PublicKey::from(&private_key);
let module_address = AuthenticationKey::ed25519(&public_key).account_address();
println!("{}", account);
println!("{}", module_address);

let rest_client = Client::new(NODE_URL.clone());
let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone()); // <:!:section_1a

// :!:>section_1b
let coin_client = CoinClient::new(&rest_client); // <:!:section_1b

// Create two accounts locally, Alice and Bob.
// :!:>section_2
let mut alice = LocalAccount::generate(&mut rand::rngs::OsRng);
let bob = LocalAccount::generate(&mut rand::rngs::OsRng); // <:!:section_2

// Print account addresses.
println!("\n=== Addresses ===");
println!("Alice: {}", alice.address().to_hex_literal());
println!("Bob: {}", bob.address().to_hex_literal());

// Create the accounts on chain, but only fund Alice.
// :!:>section_3
faucet_client
.fund(alice.address(), 100_000_000)
.await
.context("Failed to fund Alice's account")?;
faucet_client
.create_account(bob.address())
.await
.context("Failed to fund Bob's account")?; // <:!:section_3

let tx1 = send_tx(rest_client, alice, module_address, "resource_rolette", "bid", vec![], vec![10]).await?;

Ok(())

}
16 changes: 16 additions & 0 deletions process-compose/suzuka-full-node/process-compose.complex-alice.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: "3"

environment:

processes:

complex-alice-tests:
command: |
cargo test -p suzuka-client test_complex_alice
depends_on:
suzuka-full-node:
condition: process_healthy
suzuka-faucet:
condition: process_healthy
availability:
exit_on_end: true
21 changes: 21 additions & 0 deletions util/commander/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "commander"
version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
authors = { workspace = true }
repository = { workspace = true }
homepage = { workspace = true }
publish = { workspace = true }
rust-version = { workspace = true }

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = { workspace = true }
tokio = { workspace = true }
futures = { workspace = true }
tracing = { workspace = true }

[lints]
workspace = true
78 changes: 78 additions & 0 deletions util/commander/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use tokio::process::Command;
use std::process::Stdio;
use tokio::io::{self, AsyncBufReadExt, AsyncWriteExt, BufReader};
use anyhow::Result;
use futures::future::try_join;

async fn pipe_output<R: tokio::io::AsyncRead + Unpin + Send + 'static>(
reader: R,
mut writer: io::Stdout,
output: &mut String,
) -> Result<()> {
let mut reader = BufReader::new(reader).lines();
while let Ok(Some(line)) = reader.next_line().await {
writer.write_all(line.as_bytes()).await?;
writer.write_all(b"\n").await?;
output.push_str(&line);
output.push('\n');
}
Ok(())
}

async fn pipe_error_output<R: tokio::io::AsyncRead + Unpin + Send + 'static>(
reader: R,
mut writer: io::Stderr,
output: &mut String,
) -> Result<()> {
let mut reader = BufReader::new(reader).lines();
while let Ok(Some(line)) = reader.next_line().await {
writer.write_all(line.as_bytes()).await?;
writer.write_all(b"\n").await?;
output.push_str(&line);
output.push('\n');
}
Ok(())
}

/// Runs a command, piping its output to stdout and stderr, and returns the stdout output if successful.
pub async fn run_command(command: &str, args: &[&str]) -> Result<String> {

// print command out with args joined by space
println!("Running command: {} {}", command, args.join(" "));

let mut child = Command::new(command)
.args(args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;

let stdout = child.stdout.take().ok_or_else(|| {
anyhow::anyhow!("Failed to capture standard output from command {}", command)
})?;
let stderr = child.stderr.take().ok_or_else(|| {
anyhow::anyhow!("Failed to capture standard error from command {}", command)
})?;

let mut stdout_output = String::new();
let mut stderr_output = String::new();

let stdout_writer = io::stdout();
let stderr_writer = io::stderr();

let stdout_future = pipe_output(stdout, stdout_writer, &mut stdout_output);
let stderr_future = pipe_error_output(stderr, stderr_writer, &mut stderr_output);

let _ = try_join(stdout_future, stderr_future).await;

let status = child.wait().await?;
if !status.success() {
return Err(anyhow::anyhow!(
"Command {} failed with args {:?}\nError Output: {}",
command,
args,
stderr_output
));
}

Ok(stdout_output)
}

0 comments on commit bb1660c

Please sign in to comment.