Skip to content

Commit

Permalink
feat(indexer): refund sent are stored in database
Browse files Browse the repository at this point in the history
  • Loading branch information
ptisserand committed Apr 22, 2024
1 parent 1e383b4 commit 7e0c5d9
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 16 deletions.
1 change: 1 addition & 0 deletions apps/indexer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions apps/indexer/refund/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ anyhow = "1.0"
clap = { version = "4.3.19", features = ["derive", "env", "string"] }
csv = "1.3.0"
env_logger = "0.10.0"
log = "0.4.17"
futures = "0.3.28"
log = "0.4.17"
mongodb = "2.6.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
starknet = "0.10.0"
tokio = { version = "1", features = ["full"] }

starklane_indexer = { version = "0.1.0", path= ".."}
starknet = "0.10.0"
94 changes: 80 additions & 14 deletions apps/indexer/refund/src/bin/send_refund.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use std::time::Duration;
use anyhow::{anyhow, Result};
use clap::Parser;

use mongodb::{bson::doc, options::ClientOptions, Client, Collection};
use refund::Refund;
use serde::{Deserialize, Serialize};
use starklane_indexer::{storage::extract_database_name, utils::normalize_hex};
use starknet::{
accounts::{Account, Call, ConnectedAccount, ExecutionEncoding, SingleOwnerAccount},
core::{
Expand All @@ -14,6 +17,49 @@ use starknet::{
signers::{LocalWallet, SigningKey},
};

#[derive(Debug, Serialize, Deserialize)]
struct RefundSend {
pub l1_hash: String,
pub l2_hash: String,
pub refund: Refund,
}

struct MongoStore {
refunded: Collection<RefundSend>,
}

impl MongoStore {
pub async fn new(connection_string: &str, db_name: &str) -> Result<MongoStore> {
let client_options = ClientOptions::parse(connection_string).await?;
let client = Client::with_options(client_options)?;
let db = client.database(db_name);
let refunded = db.collection::<RefundSend>("refunded");

Ok(MongoStore { refunded })
}

pub async fn add(&self, l2_hash: String, refund: &Refund) -> Result<()> {
let doc = RefundSend {
l1_hash: refund.tx_hash.clone(),
l2_hash: normalize_hex(&l2_hash).unwrap(),
refund: refund.clone(),
};
self.refunded.insert_one(doc, None).await?;
Ok(())
}

pub async fn check(&self, l1_hash: String) -> Result<Option<RefundSend>> {
match self
.refunded
.find_one(doc! { "l1_hash": l1_hash}, None)
.await
{
Ok(r) => Ok(r),
Err(e) => Err(anyhow!("Failed to query DB: {:?}", e)),
}
}
}

#[derive(Parser, Debug)]
#[clap(about = "Send refund")]
struct Args {
Expand Down Expand Up @@ -49,9 +95,6 @@ fn refund_to_call(refund: &Refund) -> Call {
let decimals = 8;
let amount = refund.amount * (10_u64.pow(decimals) as f64);
let amount = (amount as u128) * (10_u64.pow(token_decimals - decimals) as u128);
// FIXME: for testing purpose!!
let amount = amount / 100;
// FIXME
let amount = FieldElement::from(amount);
Call {
to: token_address,
Expand Down Expand Up @@ -94,7 +137,6 @@ where
}
}


#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();
Expand All @@ -105,6 +147,9 @@ async fn main() -> Result<()> {
let address = args.address;
let private_key = args.private_key;

let dbname = extract_database_name(&args.mongodb)
.expect("Database name couldn't be extracted from the connection string");

let provider = JsonRpcClient::new(HttpTransport::new(Url::parse(&rpc).unwrap()));
let signer = LocalWallet::from(SigningKey::from_secret_scalar(
FieldElement::from_hex_be(&private_key).unwrap(),
Expand All @@ -114,28 +159,49 @@ async fn main() -> Result<()> {

let account =
SingleOwnerAccount::new(provider, signer, address, chain_id, ExecutionEncoding::New);

log::debug!("Account address: {:?}", account.address());
let mut calls: Vec<Call> = vec![];
let mut refunds: Vec<Refund> = vec![];

let mongo = MongoStore::new(&args.mongodb, dbname).await?;

let mut rdr = csv::Reader::from_path(input)?;
for elem in rdr.deserialize() {
let refund: Refund = elem?;
log::debug!("{:?}", refund);
if let Ok(Some(_check)) = mongo.check(refund.clone().tx_hash).await {
log::debug!("Already send: {:?}", refund);
continue;
}
log::debug!("To send: {:?}", refund);
let call = refund_to_call(&refund);
calls.push(call);
refunds.push(refund);
}

if calls.is_empty() {
log::info!("No refund to send");
return Ok(());
}
// log::debug!("Calls: {:?}", calls);

let invoke = account
.execute(calls)
.send()
.await
.unwrap();
let invoke = account.execute(calls).send().await.unwrap();
let provider = account.provider();
log::debug!("Wait for transaction: {:?}", invoke.transaction_hash);
let result = watch_tx(provider, invoke.transaction_hash, Duration::from_millis(10000)).await;
let result = watch_tx(
provider,
invoke.transaction_hash,
Duration::from_millis(10000),
)
.await;
match result {
Ok(_) => Ok(()),
Err(e) => Err(anyhow!("Transaction failed! {:?}", e))
Ok(_) => {
for refund in refunds {
let l2_hash = format!("{:#064x}", invoke.transaction_hash);
let l2_hash = normalize_hex(&l2_hash).unwrap();
mongo.add(l2_hash, &refund).await?
}
Ok(())
}
Err(e) => Err(anyhow!("Transaction failed! {:?}", e)),
}
}

0 comments on commit 7e0c5d9

Please sign in to comment.