add rudimentary VAA sending
This commit is contained in:
parent
9749044c25
commit
70a1f24220
|
@ -10,11 +10,11 @@ message Empty {
|
||||||
}
|
}
|
||||||
|
|
||||||
message SubmitVAARequest {
|
message SubmitVAARequest {
|
||||||
|
bytes vaa = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SubmitVAAResponse {
|
message SubmitVAAResponse {
|
||||||
|
string signature = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message WatchLockupsRequest {
|
message WatchLockupsRequest {
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
|
use std::env;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::mpsc::RecvError;
|
use std::sync::mpsc::RecvError;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
|
|
||||||
|
use solana_client::client_error::ClientError;
|
||||||
|
use solana_client::rpc_client::RpcClient;
|
||||||
|
use solana_sdk::fee_calculator::FeeCalculator;
|
||||||
|
use solana_sdk::instruction::Instruction;
|
||||||
use solana_sdk::program_error::ProgramError;
|
use solana_sdk::program_error::ProgramError;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::signature::{read_keypair_file, Keypair, Signer};
|
||||||
|
use solana_sdk::transaction::Transaction;
|
||||||
use spl_token::state::Account;
|
use spl_token::state::Account;
|
||||||
use tokio::stream::Stream;
|
use tokio::stream::Stream;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
@ -15,9 +22,9 @@ use tonic::{transport::Server, Code, Request, Response, Status};
|
||||||
use service::agent_server::{Agent, AgentServer};
|
use service::agent_server::{Agent, AgentServer};
|
||||||
use service::{
|
use service::{
|
||||||
lockup_event::Event, Empty, LockupEvent, LockupEventNew, LockupEventVaaPosted,
|
lockup_event::Event, Empty, LockupEvent, LockupEventNew, LockupEventVaaPosted,
|
||||||
SubmitVaaRequest, SubmitVaaResponse, VaaPostedEvent, WatchLockupsRequest, WatchVaaRequest,
|
SubmitVaaRequest, SubmitVaaResponse, WatchLockupsRequest,
|
||||||
};
|
};
|
||||||
use spl_bridge::instruction::CHAIN_ID_SOLANA;
|
use spl_bridge::instruction::{post_vaa, CHAIN_ID_SOLANA};
|
||||||
use spl_bridge::state::{Bridge, TransferOutProposal};
|
use spl_bridge::state::{Bridge, TransferOutProposal};
|
||||||
|
|
||||||
use crate::monitor::{ProgramNotificationMessage, PubsubClient};
|
use crate::monitor::{ProgramNotificationMessage, PubsubClient};
|
||||||
|
@ -28,9 +35,12 @@ pub mod service {
|
||||||
include!(concat!(env!("OUT_DIR"), concat!("/", "service", ".rs")));
|
include!(concat!(env!("OUT_DIR"), concat!("/", "service", ".rs")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct AgentImpl {
|
pub struct AgentImpl {
|
||||||
url: String,
|
url: String,
|
||||||
|
bridge: Pubkey,
|
||||||
|
|
||||||
|
rpc_url: String,
|
||||||
|
key: Keypair,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
|
@ -39,26 +49,70 @@ impl Agent for AgentImpl {
|
||||||
&self,
|
&self,
|
||||||
request: Request<SubmitVaaRequest>,
|
request: Request<SubmitVaaRequest>,
|
||||||
) -> Result<Response<SubmitVaaResponse>, Status> {
|
) -> Result<Response<SubmitVaaResponse>, Status> {
|
||||||
println!("Got a request from {:?}", request.remote_addr());
|
// Hack to clone keypair
|
||||||
|
let b = self.key.to_bytes();
|
||||||
|
let key = Keypair::from_bytes(&b).unwrap();
|
||||||
|
|
||||||
let reply = SubmitVaaResponse {};
|
let ix = match post_vaa(&self.bridge, &key.pubkey(), &request.get_ref().vaa) {
|
||||||
Ok(Response::new(reply))
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(Status::new(
|
||||||
|
Code::InvalidArgument,
|
||||||
|
format!("could not create instruction: {}", e),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut transaction = Transaction::new_with_payer(&[ix], Some(&key.pubkey()));
|
||||||
|
let rpc_url = self.rpc_url.clone();
|
||||||
|
|
||||||
|
// we need to spawn an extra thread because tokio does not allow nested runtimes
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let rpc = RpcClient::new(rpc_url);
|
||||||
|
let (recent_blockhash, fee_calculator) = match rpc.get_recent_blockhash() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(Status::new(
|
||||||
|
Code::Unavailable,
|
||||||
|
format!("could not fetch recent blockhash: {}", e),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
transaction.sign(&[&key], recent_blockhash);
|
||||||
|
match rpc.send_and_confirm_transaction(&transaction) {
|
||||||
|
Ok(s) => Ok(Response::new(SubmitVaaResponse {
|
||||||
|
signature: s.to_string(),
|
||||||
|
})),
|
||||||
|
Err(e) => Err(Status::new(
|
||||||
|
Code::Unavailable,
|
||||||
|
format!("tx sending failed: {}", e),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join()
|
||||||
|
.unwrap()
|
||||||
|
|
||||||
|
//check_fee_payer_balance(
|
||||||
|
// config,
|
||||||
|
// minimum_balance_for_rent_exemption
|
||||||
|
// + fee_calculator.calculate_fee(&transaction.message()),
|
||||||
|
//)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
type WatchLockupsStream = mpsc::Receiver<Result<LockupEvent, Status>>;
|
type WatchLockupsStream = mpsc::Receiver<Result<LockupEvent, Status>>;
|
||||||
|
|
||||||
async fn watch_lockups(
|
async fn watch_lockups(
|
||||||
&self,
|
&self,
|
||||||
_: Request<WatchLockupsRequest>,
|
req: Request<WatchLockupsRequest>,
|
||||||
) -> Result<Response<Self::WatchLockupsStream>, Status> {
|
) -> Result<Response<Self::WatchLockupsStream>, Status> {
|
||||||
let (mut tx, rx) = mpsc::channel(1);
|
let (mut tx, rx) = mpsc::channel(1);
|
||||||
let mut tx1 = tx.clone();
|
let mut tx1 = tx.clone();
|
||||||
let url = self.url.clone();
|
let url = self.url.clone();
|
||||||
|
let bridge = self.bridge.clone();
|
||||||
// creating a new task
|
// creating a new task
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
// looping and sending our response using stream
|
// looping and sending our response using stream
|
||||||
let sub =
|
let sub = PubsubClient::program_subscribe(&url, &bridge).unwrap();
|
||||||
PubsubClient::program_subscribe(&url, &Pubkey::from_str("").unwrap()).unwrap();
|
|
||||||
loop {
|
loop {
|
||||||
let item = sub.1.recv();
|
let item = sub.1.recv();
|
||||||
match item {
|
match item {
|
||||||
|
@ -136,9 +190,27 @@ impl Agent for AgentImpl {
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let addr = "[::1]:50051".parse().unwrap();
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
|
// TODO use clap
|
||||||
|
if args.len() < 6 {
|
||||||
|
println!("<bridge> <rpc_host> <rpc_port> <ws_port> <port>");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let bridge = &args[1];
|
||||||
|
let host = &args[2];
|
||||||
|
let rpc_port: u8 = args[3].parse()?;
|
||||||
|
let ws_port: u8 = args[4].parse()?;
|
||||||
|
let port: u8 = args[5].parse()?;
|
||||||
|
|
||||||
|
let addr = format!("[::1]:{}", port).parse().unwrap();
|
||||||
|
|
||||||
let agent = AgentImpl {
|
let agent = AgentImpl {
|
||||||
url: String::from("ws://localhost:8900"),
|
url: String::from(format!("ws://{}:{}", host, ws_port)),
|
||||||
|
rpc_url: format!("http://{}:{}", host, rpc_port),
|
||||||
|
bridge: Pubkey::from_str(bridge).unwrap(),
|
||||||
|
key: Keypair::new(), // TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Agent listening on {}", addr);
|
println!("Agent listening on {}", addr);
|
||||||
|
|
Loading…
Reference in New Issue