Skip to content

Commit

Permalink
wip: reachability test
Browse files Browse the repository at this point in the history
  • Loading branch information
0xdeafbeef committed Jun 27, 2024
1 parent fb26aa7 commit f2f76de
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 48 deletions.
177 changes: 129 additions & 48 deletions client/examples/multisig.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
use std::io::Write;
use std::str::FromStr;
use std::time::Duration;

use ed25519_dalek::Signer;
use nekoton::core::models::Expiration;
use nekoton::core::ton_wallet::multisig::prepare_transfer;
use nekoton::core::ton_wallet::{Gift, MultisigType, TransferAction, WalletType};
use nekoton::crypto::MnemonicType;
use ton_block::{GetRepresentationHash, MsgAddressInt};
use nekoton::crypto::{extend_with_signature_id, MnemonicType};
use reqwest::Client;
use serde_json::json;
use ton_block::{GetRepresentationHash, MsgAddressInt, Serializable};

use everscale_rpc_client::{ClientOptions, SendOptions, SendStatus, TransportErrorAction};
use everscale_rpc_client::{
ClientOptions, RpcClient, SendOptions, SendStatus, TransportErrorAction,
};

#[tokio::main]
async fn main() {
tracing_subscriber::fmt::SubscriberBuilder::default()
.with_max_level(tracing::Level::DEBUG)
.with_env_filter(tracing_subscriber::EnvFilter::new(
"everscale_rpc_client=info",
))
.init();

let mut times = std::fs::File::create("times.txt").unwrap();
let seed = std::env::args().nth(1).unwrap();
let to = std::env::args().nth(2).unwrap();

let to = MsgAddressInt::from_str(&to).expect("invalid address");

let client = everscale_rpc_client::RpcClient::new(
["https://jrpc.everwallet.net/rpc".parse().unwrap()],
["https://jrpc.venom.foundation/rpc".parse().unwrap()],
ClientOptions::default(),
)
.await
Expand All @@ -35,54 +44,126 @@ async fn main() {
WalletType::Multisig(MultisigType::SafeMultisigWallet),
0,
);
let mut succesful = 0;
let mut failed = 0;

let tx = prepare_transfer(
&nekoton::utils::SimpleClock,
MultisigType::SafeMultisigWallet,
&signer.public,
false,
from,
Gift {
flags: 3,
bounce: false,
destination: to,
amount: 1_000_000_000,
// can be built with `nekoton_abi::MessageBuilder`
body: None,
state_init: None,
},
Expiration::Timeout(60),
)
.unwrap();
let num_send = 30;

for i in 0..num_send {
let start = std::time::Instant::now();
let tx = prepare_transfer(
&nekoton::utils::SimpleClock,
MultisigType::SafeMultisigWallet,
&signer.public,
false,
from.clone(),
Gift {
flags: 3,
bounce: false,
destination: to.clone(),
amount: 1_000_000,
// can be built with `nekoton_abi::MessageBuilder`
body: None,
state_init: None,
},
Expiration::Timeout(60),
)
.unwrap();

let message = match tx {
TransferAction::DeployFirst => {
panic!("DeployFirst not supported")
}
TransferAction::Sign(m) => m,
};

let message = match tx {
TransferAction::DeployFirst => {
panic!("DeployFirst not supported")
let signature = signer
.sign(&*extend_with_signature_id(message.hash(), Some(1)))
.to_bytes();
let signed_message = message.sign(&signature).expect("invalid signature");

let message = signed_message.message;
let send_options = SendOptions {
error_action: TransportErrorAction::Return,
ttl: Duration::from_secs(60),
poll_interval: Duration::from_millis(100),
};

let cell = message
.write_to_new_cell()
.and_then(ton_types::BuilderData::into_cell)
.unwrap();
let boc = base64::encode(ton_types::serialize_toc(&cell).unwrap());
let id = base64::encode(cell.repr_hash());
let status = send_gql(boc, id, *cell.repr_hash().as_slice(), &client)
.await
.unwrap();
// let status = client
// .send_message(message, send_options)
// .await
// .expect("failed to send message");
match status {
SendStatus::Confirmed(tx) => {
succesful += 1;
println!("tx: {}", tx.hash().unwrap().to_hex_string());
}
SendStatus::Expired => {
println!("Message expired");
failed += 1;
}
_ => { /* this method doesn't return other statuses */ }
}
TransferAction::Sign(m) => m,
};

let signature = signer.sign(message.hash()).to_bytes();
let signed_message = message.sign(&signature).expect("invalid signature");

let message = signed_message.message;
let send_options = SendOptions {
error_action: TransportErrorAction::Return,
ttl: Duration::from_secs(60),
poll_interval: Duration::from_secs(1),
};

let status = client
.send_message(message, send_options)
.await
.expect("failed to send message");
match status {
SendStatus::Confirmed(tx) => {
println!("tx: {}", tx.hash().unwrap().to_hex_string());

let elapsed = start.elapsed();
// times.push(elapsed.as_millis());
times
.write_all(format!("{},{}\n", i, elapsed.as_millis()).as_bytes())
.unwrap();
println!("Send {i} of {num_send} messages",);
}
println!("Succesful: {}, failed: {}", succesful, failed);
}

#[derive(Debug, serde::Serialize)]
struct GraphQLQuery<'a> {
query: &'a str,
variables: serde_json::Value,
}

async fn send_gql(
message: String,
id: String,
x: [u8; 32],
rpc: &RpcClient,
) -> anyhow::Result<SendStatus> {
let client = Client::new();
let query = "mutation($id:String!,$boc:String!){postRequests(requests:[{id:$id,body:$boc}])}";

let variables = json!({
"id": id,
"boc": message,
});

let gql_query = GraphQLQuery { query, variables };

let res = client
// .post("https://gql.venom.foundation/graphql") // Specify the URL
.post("http://57.128.125.221:8080/graphql") // Specify the URL
.json(&gql_query) // Pass the constructed query payload
.send()
.await?;

let res_text = res.text().await?;
println!("Response: {}", res_text);
let polling_start = std::time::Instant::now();

loop {
let tx = rpc.get_dst_transaction(&x).await?;
if tx.is_some() {
return Ok(SendStatus::Confirmed(tx.unwrap()));
}
SendStatus::Expired => {
println!("Message expired");
if polling_start.elapsed().as_secs() > 60 {
return Ok(SendStatus::Expired);
}
_ => { /* this method doesn't return other statuses */ }
}
}
95 changes: 95 additions & 0 deletions client/examples/send_message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use ed25519_dalek::{Keypair, PublicKey};
use nekoton::core::ton_wallet::TransferAction;
use nekoton::models::Expiration;
use nekoton_utils::{SimpleClock, TrustMe};
use serde::{Deserialize, Serialize};
use ton_abi::sign_with_signature_id;
use ton_block::{GetRepresentationHash, MsgAddressInt};
use ton_types::{BuilderData, IBitstring, SliceData};

fn main() {
let wallet = nekoton::core::ton_wallet::ever_wallet::prepare_transfer();
}

async fn send(
client: &everscale_rpc_client::RpcClient,
signer: &Keypair,
nonce: u64,
payload: BuilderData,
destination: MsgAddressInt,
amount: u64,
sign_id: Option<i32>,
) -> anyhow::Result<()> {
let addres = compute_contract_address(&pub_key, 0, nonce);
let state = client.get_contract_state(&addres, None).await?.unwrap();
let gift = nekoton::core::ton_wallet::ever_wallet::Gift {
flags: 3,
bounce: false,
destination,
amount,
body: Some(SliceData::load_builder(payload)?),
state_init: None,
};

let now = nekoton_utils::now_sec_u64() as u32 + 60;

let message = nekoton::core::ton_wallet::ever_wallet::prepare_transfer(
&SimpleClock,
&pub_key,
&state.account,
addres,
vec![gift],
Expiration::Timestamp(now),
)?;
let message = match message {
TransferAction::DeployFirst => {
panic!("DeployFirst not supported")
}
TransferAction::Sign(m) => m,
};
let signature = sign_with_signature_id(signer, message.hash(), sign_id);
let signed_message = message.sign(&signature).trust_me().message;

client.broadcast_message(signed_message).await?;

Ok(())
}

pub fn compute_contract_address(
public_key: &PublicKey,
workchain_id: i8,
nonce: u64,
) -> MsgAddressInt {
let hash = make_state_init(public_key, nonce)
.and_then(|state| state.hash())
.trust_me();
MsgAddressInt::AddrStd(ton_block::MsgAddrStd::with_address(
None,
workchain_id,
hash.into(),
))
}

pub fn make_state_init(public_key: &PublicKey, nonce: u64) -> anyhow::Result<ton_block::StateInit> {
let mut data = BuilderData::new();
data.append_raw(public_key.as_bytes(), 256)?
.append_u64(nonce)?;
let data = data.into_cell()?;

Ok(ton_block::StateInit {
code: Some(nekoton_contracts::wallets::code::ever_wallet()),
data: Some(data),
..Default::default()
})
}

#[derive(Serialize, Deserialize)]
struct CreateAccountParams {
pub nonce: i64,
}

#[derive(Serialize, Deserialize)]
struct Root {
#[serde(rename = "createAccountParams")]
pub create_account_params: CreateAccountParams,
}

0 comments on commit f2f76de

Please sign in to comment.