improve logging during payment parsing

This commit is contained in:
Bryan Stitt 2023-07-26 16:39:17 -07:00
parent 9bc1e5a783
commit 788ebff29f

@ -308,121 +308,128 @@ pub async fn user_balance_post(
let mut response_data = vec![]; let mut response_data = vec![];
for log in transaction_receipt.logs { for log in transaction_receipt.logs {
if let Some(true) = log.removed { if let Some(true) = log.removed {
debug!(?log, "log removed");
// TODO: do we need to make sure this row is deleted? it should be handled by `handle_uncle_block` // TODO: do we need to make sure this row is deleted? it should be handled by `handle_uncle_block`
continue; continue;
} }
if log.address != payment_factory_address { if log.address != payment_factory_address {
trace!(?log, ?payment_factory_address, "wrong log address");
continue; continue;
} }
info!(?log, "likely relevant");
// Parse the log into an event // Parse the log into an event
if let Ok(event) = payment_factory_contract match payment_factory_contract.decode_event::<payment_factory::PaymentReceivedFilter>(
.decode_event::<payment_factory::PaymentReceivedFilter>( "PaymentReceived",
"PaymentReceived", log.topics,
log.topics, log.data,
log.data, ) {
) Err(err) => debug!(?err, "failed parsing log as PaymentReceived"),
{ Ok(event) => {
let recipient_account = event.account; let recipient_account = event.account;
let payment_token_address = event.token; let payment_token_address = event.token;
let payment_token_wei = event.amount; let payment_token_wei = event.amount;
// there is no need to check that payment_token_address is an allowed token // there is no need to check that payment_token_address is an allowed token
// the smart contract already reverts if the token isn't accepted // the smart contract already reverts if the token isn't accepted
// we used to skip here if amount is 0, but that means the txid wouldn't ever show up in the database which could be confusing // we used to skip here if amount is 0, but that means the txid wouldn't ever show up in the database which could be confusing
// its irrelevant though because the contract already reverts for 0 value // its irrelevant though because the contract already reverts for 0 value
let log_index = log let log_index = log
.log_index .log_index
.context("no log_index. transaction must not be confirmed")? .context("no log_index. transaction must not be confirmed")?
.as_u64(); .as_u64();
// the internal provider will handle caching of requests // the internal provider will handle caching of requests
let payment_token = IERC20::new(payment_token_address, app.internal_provider().clone()); let payment_token =
IERC20::new(payment_token_address, app.internal_provider().clone());
// get the decimals for the token // get the decimals for the token
// hopefully u32 is always enough, because the Decimal crate doesn't accept a larger scale // hopefully u32 is always enough, because the Decimal crate doesn't accept a larger scale
// <https://eips.ethereum.org/EIPS/eip-20> uses uint8, but i've seen pretty much every int in practice // <https://eips.ethereum.org/EIPS/eip-20> uses uint8, but i've seen pretty much every int in practice
let payment_token_decimals = payment_token.decimals().call().await?.as_u32(); let payment_token_decimals = payment_token.decimals().call().await?.as_u32();
let mut payment_token_amount = Decimal::from_str_exact(&payment_token_wei.to_string())?; let mut payment_token_amount =
// Setting the scale already does the decimal shift, no need to divide a second time Decimal::from_str_exact(&payment_token_wei.to_string())?;
payment_token_amount.set_scale(payment_token_decimals)?; // Setting the scale already does the decimal shift, no need to divide a second time
payment_token_amount.set_scale(payment_token_decimals)?;
trace!( trace!(
"found deposit event for: {:?} {:?} {:?}", "found deposit event for: {:?} {:?} {:?}",
recipient_account, recipient_account,
payment_token_address, payment_token_address,
payment_token_amount payment_token_amount
); );
let txn = db_conn.begin().await?; let txn = db_conn.begin().await?;
let (recipient, recipient_tier) = let (recipient, recipient_tier) =
match get_user_and_tier_from_address(&recipient_account, &txn).await? { match get_user_and_tier_from_address(&recipient_account, &txn).await? {
Some(x) => x, Some(x) => x,
None => { None => {
let (user, _) = register_new_user(&txn, recipient_account).await?; let (user, _) = register_new_user(&txn, recipient_account).await?;
(user, None) (user, None)
} }
};
// For now we only accept stablecoins. This will need conversions if we accept other tokens.
// 1$ = Decimal(1) for any stablecoin
// TODO: Let's assume that people don't buy too much at _once_, we do support >$1M which should be fine for now
// TODO: double check. why >$1M? Decimal type in the database?
trace!(
"Arithmetic is: {:?} / 10 ^ {:?} = {:?}",
payment_token_wei,
payment_token_decimals,
payment_token_amount
);
trace!("Saving log {} of txid {:?}", log_index, tx_hash);
let receipt = increase_on_chain_balance_receipt::ActiveModel {
id: sea_orm::ActiveValue::NotSet,
amount: sea_orm::ActiveValue::Set(payment_token_amount),
block_hash: sea_orm::ActiveValue::Set(block_hash.encode_hex()),
chain_id: sea_orm::ActiveValue::Set(app.config.chain_id),
deposit_to_user_id: sea_orm::ActiveValue::Set(recipient.id),
log_index: sea_orm::ActiveValue::Set(log_index),
token_address: sea_orm::ActiveValue::Set(payment_token_address.encode_hex()),
tx_hash: sea_orm::ActiveValue::Set(tx_hash.encode_hex()),
date_created: sea_orm::ActiveValue::NotSet,
}; };
trace!("Trying to insert receipt {:?}", receipt);
// For now we only accept stablecoins. This will need conversions if we accept other tokens. receipt.save(&txn).await?;
// 1$ = Decimal(1) for any stablecoin
// TODO: Let's assume that people don't buy too much at _once_, we do support >$1M which should be fine for now
// TODO: double check. why >$1M? Decimal type in the database?
trace!(
"Arithmetic is: {:?} / 10 ^ {:?} = {:?}",
payment_token_wei,
payment_token_decimals,
payment_token_amount
);
trace!("Saving log {} of txid {:?}", log_index, tx_hash); grant_premium_tier(&recipient, recipient_tier.as_ref(), &txn)
let receipt = increase_on_chain_balance_receipt::ActiveModel { .await
id: sea_orm::ActiveValue::NotSet, .web3_context("granting premium tier")?;
amount: sea_orm::ActiveValue::Set(payment_token_amount),
block_hash: sea_orm::ActiveValue::Set(block_hash.encode_hex()),
chain_id: sea_orm::ActiveValue::Set(app.config.chain_id),
deposit_to_user_id: sea_orm::ActiveValue::Set(recipient.id),
log_index: sea_orm::ActiveValue::Set(log_index),
token_address: sea_orm::ActiveValue::Set(payment_token_address.encode_hex()),
tx_hash: sea_orm::ActiveValue::Set(tx_hash.encode_hex()),
date_created: sea_orm::ActiveValue::NotSet,
};
trace!("Trying to insert receipt {:?}", receipt);
receipt.save(&txn).await?; txn.commit().await?;
grant_premium_tier(&recipient, recipient_tier.as_ref(), &txn) let x = json!({
.await "amount": payment_token_amount,
.web3_context("granting premium tier")?; "block_hash": block_hash,
"log_index": log_index,
"recipient_account": recipient_account,
"token": payment_token_address,
"tx_hash": tx_hash,
});
txn.commit().await?; debug!("deposit data: {:#?}", x);
let x = json!({ response_data.push(x);
"amount": payment_token_amount,
"block_hash": block_hash,
"log_index": log_index,
"recipient_account": recipient_account,
"token": payment_token_address,
"tx_hash": tx_hash,
});
debug!("deposit data: {:#?}", x); // invalidate the cache as well
if let Err(err) = app
response_data.push(x); .user_balance_cache
.invalidate(&recipient.id, &db_conn, &app.rpc_secret_key_cache)
// invalidate the cache as well .await
if let Err(err) = app {
.user_balance_cache warn!(?err, user_id=%recipient.id, "unable to invalidate cache");
.invalidate(&recipient.id, &db_conn, &app.rpc_secret_key_cache) };
.await }
{
warn!(?err, user_id=%recipient.id, "unable to invalidate cache");
};
} }
} }